--- a/ConfigTree.py Tue May 08 16:31:12 2012 +0200
+++ b/ConfigTree.py Tue May 08 17:08:45 2012 +0200
@@ -4,7 +4,7 @@
from xml.dom import minidom
@@ -752,7 +752,7 @@
# For root object, available Children Types are modules of the confnode packages.
- CTNChildrenTypes = [(n, CTNClassFactory(c), d) for n,d,h,c in confnodes.catalog]
+ CTNChildrenTypes = [(n, CTNClassFactory(c), d) for n,d,h,c in features.catalog] XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
@@ -1054,7 +1054,7 @@
- return os.path.join(os.path.split(__file__)[0], "confnodes")
+ return os.path.split(__file__)[0] def CTNPath(self, CTNName=None):
@@ -1480,13 +1480,12 @@
self.ResetIECProgramsAndVariables()
# Generate C code and compilation params from confnode hierarchy
- self.logger.write(_("Generating confnodes C code\n"))
self.LocationCFilesAndCFLAGS, self.LDFLAGS, ExtraFiles = self._Generate_C(
self.PLCGeneratedLocatedVars)
- self.logger.write_error(_("ConfNodes code generation failed !\n"))
+ self.logger.write_error(_("Runtime extensions C code generation failed !\n")) self.logger.write_error(traceback.format_exc())
--- a/LPCBeremiz.py Tue May 08 16:31:12 2012 +0200
+++ b/LPCBeremiz.py Tue May 08 17:08:45 2012 +0200
@@ -67,8 +67,8 @@
- from confnodes.canfestival import RootClass as CanOpenRootClass
- from confnodes.canfestival.canfestival import _SlaveCTN, _NodeListCTN, NodeManager
+ from canfestival import RootClass as CanOpenRootClass + from canfestival.canfestival import _SlaveCTN, _NodeListCTN, NodeManager @@ -77,7 +77,7 @@
#-------------------------------------------------------------------------------
# CANFESTIVAL CONFNODE HACK
#-------------------------------------------------------------------------------
-# from confnodes.canfestival import canfestival
+# from canfestival import canfestival # class LPC_canfestival_config:
# def getCFLAGS(self, *args):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/.cvsignore Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/CFileEditor.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,967 @@
+from controls import CustomGrid, CustomTable, EditorPanel +if wx.Platform == '__WXMSW__': + faces = { 'times': 'Times New Roman', + 'mono' : 'Courier New', + 'other': 'Comic Sans MS', + faces = { 'times': 'Times', + 'other': 'new century schoolbook', +def AppendMenu(parent, help, id, kind, text): + if wx.VERSION >= (2, 6, 0): + parent.Append(help=help, id=id, kind=kind, text=text) + parent.Append(helpString=help, id=id, kind=kind, item=text) +] = [wx.NewId() for _init_ctrls in range(1)] +CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", + "const", "const_cast", "continue", "default", "delete", "do", "double", + "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", + "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", + "namespace", "new", "operator", "private", "protected", "public", "register", + "reinterpret_cast", "return", "short", "signed", "sizeof", "static", + "static_cast", "struct", "switch", "template", "this", "throw", "true", "try", + "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", + "void", "volatile", "wchar_t", "while"] +def GetCursorPos(old, new): + common_length = min(old_length, new_length) + for i in xrange(common_length): + if old_length < new_length: + if common_length > 0 and old[i] != new[i]: + return i + new_length - old_length + return i + new_length - old_length + 1 + elif old_length > new_length or i < min(old_length, new_length) - 1: + if common_length > 0 and old[i] != new[i]: +class CppEditor(stc.StyledTextCtrl): + def __init__(self, parent, name, window, controler): + stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, + self.SetMarginType(1, stc.STC_MARGIN_NUMBER) + self.SetMarginWidth(1, 25) + self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN) + self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT) + self.SetLexer(stc.STC_LEX_CPP) + self.SetKeyWords(0, " ".join(CPP_KEYWORDS)) + self.SetProperty("fold", "1") + self.SetProperty("tab.timmy.whinge.level", "1") + self.SetViewWhiteSpace(False) + #self.SetBufferedDraw(False) + #self.SetEOLMode(stc.STC_EOL_CRLF) + #self.SetUseAntiAliasing(True) + self.SetEdgeMode(stc.STC_EDGE_BACKGROUND) + # Setup a margin to hold fold markers + #self.SetFoldFlags(16) ### WHAT IS THIS VALUE? WHAT ARE THE OTHER FLAGS? DOES IT MATTER? + self.SetMarginType(2, stc.STC_MARGIN_SYMBOL) + self.SetMarginMask(2, stc.STC_MASK_FOLDERS) + self.SetMarginSensitive(2, True) + self.SetMarginWidth(2, 12) + if self.fold_symbols == 0: + # Arrow pointing right for contracted folders, arrow pointing down for expanded + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") + elif self.fold_symbols == 1: + # Plus for contracted folders, minus for expanded + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") + elif self.fold_symbols == 2: + # Like a flattened tree control using circular headers and curved joins + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") + elif self.fold_symbols == 3: + # Like a flattened tree control using square headers + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080") + self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080") + self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) + self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed) + # Make some styles, The lexer defines what each style is used for, we + # just have to define what each style looks like. This set is adapted from + # Scintilla sample property files. + # Global default styles for all languages + self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces) + self.StyleClearAll() # Reset all to be like the default + # Global default styles for all languages + self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces) + self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces) + self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces) + self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold") + self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold") + self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060') + self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060') + self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060') + self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE') + self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056') + self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff') + self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056') + self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold') + self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF') + # register some images for use in the AutoComplete box. + #self.RegisterImage(1, images.getSmilesBitmap()) + wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) + wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16))) + wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16))) + self.Controler = controler + self.ParentWindow = window + self.DisableEvents = True + self.CurrentAction = None + self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) + self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR) + self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR) + def OnModification(self, event): + if not self.DisableEvents: + mod_type = event.GetModificationType() + if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO): + if mod_type&wx.stc.STC_MOD_BEFOREINSERT: + if self.CurrentAction == None: + elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1: + self.Controler.EndBuffering() + self.CurrentAction = ("Add", event.GetPosition()) + wx.CallAfter(self.RefreshModel) + elif mod_type&wx.stc.STC_MOD_BEFOREDELETE: + if self.CurrentAction == None: + elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1: + self.Controler.EndBuffering() + self.CurrentAction = ("Delete", event.GetPosition()) + wx.CallAfter(self.RefreshModel) + def OnDoDrop(self, event): + wx.CallAfter(self.RefreshModel) + # Buffer the last model state + def RefreshBuffer(self): + self.Controler.BufferCFile() + if self.ParentWindow is not None: + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshFileMenu() + self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshPageTitles() + def StartBuffering(self): + self.Controler.StartBuffering() + if self.ParentWindow is not None: + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshFileMenu() + self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshPageTitles() + if self.CurrentAction != None: + self.Controler.EndBuffering() + self.CurrentAction = None + self.DisableEvents = True + old_cursor_pos = self.GetCurrentPos() + old_text = self.GetText() + new_text = self.Controler.GetPartText(self.Name) + new_cursor_pos = GetCursorPos(old_text, new_text) + if new_cursor_pos != None: + self.GotoPos(new_cursor_pos) + self.GotoPos(old_cursor_pos) + self.DisableEvents = False + def DoGetBestSize(self): + return self.ParentWindow.GetPanelBestSize() + def RefreshModel(self): + self.Controler.SetPartText(self.Name, self.GetText()) + def OnKeyPressed(self, event): + if self.CallTipActive(): + key = event.GetKeyCode() + if key == 32 and event.ControlDown(): + pos = self.GetCurrentPos() +## self.CallTipSetBackground("yellow") +## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n' +## 'show some suff, maybe parameters..\n\n' +## 'fubar(param1, param2)') + self.AutoCompSetIgnoreCase(False) # so this needs to match + # Images are specified with a appended "?type" + self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS])) + def OnKillFocus(self, event): + def OnUpdateUI(self, evt): + # check for matching braces + caretPos = self.GetCurrentPos() + charBefore = self.GetCharAt(caretPos - 1) + styleBefore = self.GetStyleAt(caretPos - 1) + if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR: + braceAtCaret = caretPos - 1 + charAfter = self.GetCharAt(caretPos) + styleAfter = self.GetStyleAt(caretPos) + if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR: + braceAtCaret = caretPos + braceOpposite = self.BraceMatch(braceAtCaret) + if braceAtCaret != -1 and braceOpposite == -1: + self.BraceBadLight(braceAtCaret) + self.BraceHighlight(braceAtCaret, braceOpposite) + #pt = self.PointFromPosition(braceOpposite) + #self.Refresh(True, wxRect(pt.x, pt.y, 5,5)) + def OnMarginClick(self, evt): + # fold and unfold as needed + if evt.GetMargin() == 2: + if evt.GetShift() and evt.GetControl(): + lineClicked = self.LineFromPosition(evt.GetPosition()) + if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: + self.SetFoldExpanded(lineClicked, True) + self.Expand(lineClicked, True, True, 1) + if self.GetFoldExpanded(lineClicked): + self.SetFoldExpanded(lineClicked, False) + self.Expand(lineClicked, False, True, 0) + self.SetFoldExpanded(lineClicked, True) + self.Expand(lineClicked, True, True, 100) + self.ToggleFold(lineClicked) + lineCount = self.GetLineCount() + # find out if we are folding or unfolding + for lineNum in range(lineCount): + if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: + expanding = not self.GetFoldExpanded(lineNum) + while lineNum < lineCount: + level = self.GetFoldLevel(lineNum) + if level & stc.STC_FOLDLEVELHEADERFLAG and \ + (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: + self.SetFoldExpanded(lineNum, True) + lineNum = self.Expand(lineNum, True) + lastChild = self.GetLastChild(lineNum, -1) + self.SetFoldExpanded(lineNum, False) + if lastChild > lineNum: + self.HideLines(lineNum+1, lastChild) + def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): + lastChild = self.GetLastChild(line, level) + while line <= lastChild: + self.ShowLines(line, line) + self.HideLines(line, line) + self.ShowLines(line, line) + level = self.GetFoldLevel(line) + if level & stc.STC_FOLDLEVELHEADERFLAG: + self.SetFoldExpanded(line, True) + self.SetFoldExpanded(line, False) + line = self.Expand(line, doExpand, force, visLevels-1) + if doExpand and self.GetFoldExpanded(line): + line = self.Expand(line, True, force, visLevels-1) + line = self.Expand(line, False, force, visLevels-1) + self.DisableEvents = True + self.CmdKeyExecute(wx.stc.STC_CMD_CUT) + self.DisableEvents = False + self.CmdKeyExecute(wx.stc.STC_CMD_COPY) + self.DisableEvents = True + self.CmdKeyExecute(wx.stc.STC_CMD_PASTE) + self.DisableEvents = False +#------------------------------------------------------------------------------- +# Helper for VariablesGrid values +#------------------------------------------------------------------------------- +class VariablesTable(CustomTable): + def GetValue(self, row, col): + if row < self.GetNumberRows(): + return str(self.data[row].get(self.GetColLabelValue(col, False), "")) + def _updateColAttrs(self, grid): + wxGrid -> update the column attributes to add the + appropriate renderer given the column name. + Otherwise default to the default renderer. + for row in range(self.GetNumberRows()): + for col in range(self.GetNumberCols()): + colname = self.GetColLabelValue(col, False) + editor = wx.grid.GridCellTextEditor() + elif colname == "Class": + editor = wx.grid.GridCellChoiceEditor() + editor.SetParameters("input,memory,output") + elif colname == "Type": + grid.SetReadOnly(row, col, True) + grid.SetCellEditor(row, col, editor) + grid.SetCellRenderer(row, col, renderer) + grid.SetCellBackgroundColour(row, col, wx.WHITE) + self.ResizeRow(grid, row) +[ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID, + ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON, + ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON +] = [wx.NewId() for _init_ctrls in range(6)] +class VariablesEditor(wx.Panel): + if wx.VERSION < (2, 6, 0): + def Bind(self, event, function, id = None): + event(self, id, function) + def _init_coll_MainSizer_Growables(self, parent): + parent.AddGrowableCol(0) + parent.AddGrowableRow(0) + def _init_coll_MainSizer_Items(self, parent): + parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW) + parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW) + def _init_coll_ButtonsSizer_Growables(self, parent): + parent.AddGrowableCol(0) + parent.AddGrowableRow(0) + def _init_coll_ButtonsSizer_Items(self, parent): + parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT) + parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0) + parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0) + parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0) + def _init_sizers(self): + self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4) + self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0) + self._init_coll_MainSizer_Growables(self.MainSizer) + self._init_coll_MainSizer_Items(self.MainSizer) + self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer) + self._init_coll_ButtonsSizer_Items(self.ButtonsSizer) + self.SetSizer(self.MainSizer) + def _init_ctrls(self, prnt): + wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt, + size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) + self.VariablesGrid = CustomGrid(id=ID_VARIABLESEDITORVARIABLESGRID, + name='VariablesGrid', parent=self, pos=wx.Point(0, 0), + size=wx.Size(-1, -1), style=wx.VSCROLL) + if wx.VERSION >= (2, 5, 0): + self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange) + self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick) + self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown) + wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange) + wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick) + wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown) + self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable', + name='AddVariableButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(122, 32), style=0) + self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable', + name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(122, 32), style=0) + self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^', + name='UpVariableButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v', + name='DownVariableButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + def __init__(self, parent, window, controler): + self._init_ctrls(parent) + self.ParentWindow = window + self.Controler = controler + self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""} + self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"]) + self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT] + self.ColSizes = [40, 200, 150, 150] + self.VariablesGrid.SetTable(self.Table) + self.VariablesGrid.SetButtons({"Add": self.AddVariableButton, + "Delete": self.DeleteVariableButton, + "Up": self.UpVariableButton, + "Down": self.DownVariableButton}) + def _AddVariable(new_row): + self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy()) + setattr(self.VariablesGrid, "_AddRow", _AddVariable) + def _DeleteVariable(row): + self.Table.RemoveRow(row) + setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable) + def _MoveVariable(row, move): + new_row = self.Table.MoveRow(row, move) + setattr(self.VariablesGrid, "_MoveRow", _MoveVariable) + self.VariablesGrid.SetRowLabelSize(0) + for col in range(self.Table.GetNumberCols()): + attr = wx.grid.GridCellAttr() + attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE) + self.VariablesGrid.SetColAttr(col, attr) + self.VariablesGrid.SetColSize(col, self.ColSizes[col]) + self.Table.ResetView(self.VariablesGrid) + def RefreshModel(self): + self.Controler.SetVariables(self.Table.GetData()) + # Buffer the last model state + def RefreshBuffer(self): + self.Controler.BufferCFile() + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshFileMenu() + self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshPageTitles() + self.Table.SetData(self.Controler.GetVariables()) + self.Table.ResetView(self.VariablesGrid) + self.VariablesGrid.RefreshButtons() + def DoGetBestSize(self): + return self.ParentWindow.GetPanelBestSize() + def OnVariablesGridCellChange(self, event): + wx.CallAfter(self.RefreshView) + def OnVariablesGridEditorShown(self, event): + row, col = event.GetRow(), event.GetCol() + if self.Table.GetColLabelValue(col) == "Type": + type_menu = wx.Menu(title='') + base_menu = wx.Menu(title='') + for base_type in self.Controler.GetBaseTypes(): + AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type) + self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id) + type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu) + datatype_menu = wx.Menu(title='') + for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True): + AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype) + self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id) + type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu) + rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col)) + self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize()) + def GetVariableTypeFunction(self, base_type): + def VariableTypeFunction(event): + row = self.VariablesGrid.GetGridCursorRow() + self.Table.SetValueByName(row, "Type", base_type) + self.Table.ResetView(self.VariablesGrid) + return VariableTypeFunction + def OnVariablesGridCellLeftClick(self, event): + if event.GetCol() == 0: + if self.Table.GetValueByName(row, "Class") == "input": + if self.Table.GetValueByName(i, "Class") == "input": + elif self.Table.GetValueByName(row, "Class") == "memory": + if self.Table.GetValueByName(i, "Class") == "memory": + if self.Table.GetValueByName(i, "Class") == "output": + data_type = self.Table.GetValueByName(row, "Type") + var_name = self.Table.GetValueByName(row, "Name") + base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation())) + location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num) + data = wx.TextDataObject(str((location, "location", data_type, var_name, ""))) + dragSource = wx.DropSource(self.VariablesGrid) + dragSource.SetData(data) + dragSource.DoDragDrop() +#------------------------------------------------------------------------------- +# SVGUIEditor Main Frame Class +#------------------------------------------------------------------------------- + ("Includes", CppEditor), + ("Variables", VariablesEditor), + ("Globals", CppEditor), + ("CleanUp", CppEditor), + ("Retrieve", CppEditor), + ("Publish", CppEditor), +#---------------------------------------------------------------------- +# different icons for the collapsed/expanded states. +# Taken from standard Windows XP collapsed/expanded states. +#---------------------------------------------------------------------- +def GetCollapsedIconData(): +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\ +\xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\ +\xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\ +H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\ +\xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\ +\xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\ +\x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\ +\xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\ +zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\ +\x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\ +~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\ +\x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\ +\xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\ +\xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\ +0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\ +\x00\x00\x00IEND\xaeB`\x82' +def GetCollapsedIconBitmap(): + return wx.BitmapFromImage(GetCollapsedIconImage()) +def GetCollapsedIconImage(): + stream = cStringIO.StringIO(GetCollapsedIconData()) + return wx.ImageFromStream(stream) +#---------------------------------------------------------------------- +def GetExpandedIconData(): +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\ +\xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\ +\x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\ +\xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\ +\x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\ +\x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\ +\x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\ +\xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\ +\x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\ +\x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\ +\xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\ +\xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\ +\x05\x10\x81\xce\xc9\xa8\xf6><G\xd8\xed\xbbA)X\xd9\x0c\x01\x9a\xc6Q\x14\xd9h\ +[\x04\xda\xd6c\xadFkE\xf0\xc2\xab\xd7\xb7\xc9\x08\x00\xf8\xf6\xbd\x1b\x8cQ\ +\xd8|\xb9\x0f\xd3\x9a\x8a\xc7\x08\x00\x9f?\xdd%\xde\x07\xda\x93\xc3{\x19C\ +\x8a\x9c\x03\x0b8\x17\xe8\x9d\xbf\x02.>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\ +\xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\ +def GetExpandedIconBitmap(): + return wx.BitmapFromImage(GetExpandedIconImage()) +def GetExpandedIconImage(): + stream = cStringIO.StringIO(GetExpandedIconData()) + return wx.ImageFromStream(stream) +class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton): + def GetBackgroundBrush(self, dc): + colBg = self.GetBackgroundColour() + brush = wx.Brush(colBg, wx.SOLID) + if self.style & wx.BORDER_NONE: + myAttr = self.GetDefaultAttributes() + parAttr = self.GetParent().GetDefaultAttributes() + myDef = colBg == myAttr.colBg + parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg + if wx.Platform == "__WXMAC__": + brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive + elif wx.Platform == "__WXMSW__": + if self.DoEraseBackground(dc): + elif myDef and not parDef: + colBg = self.GetParent().GetBackgroundColour() + brush = wx.Brush(colBg, wx.SOLID) + def DrawLabel(self, dc, width, height, dx=0, dy=0): + if bmp is not None: # if the bitmap is used + if self.bmpDisabled and not self.IsEnabled(): + if self.bmpFocus and self.hasFocus: + if self.bmpSelected and not self.up: + bw,bh = bmp.GetWidth(), bmp.GetHeight() + hasMask = bmp.GetMask() is not None + bw = bh = 0 # no bitmap -> size is zero + dc.SetFont(self.GetFont()) + dc.SetTextForeground(self.GetForegroundColour()) + dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + label = self.GetLabel() + tw, th = dc.GetTextExtent(label) # size of text + dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available + dc.DrawText(label, 2, (height-th)/2) # draw the text + dc.SetPen(wx.Pen(self.GetForegroundColour())) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.DrawRectangle(0, 0, width, height) +[ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER, + ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED, +] = [wx.NewId() for _init_ctrls in range(4)] +class CFileEditor(EditorPanel): + def _init_Editor(self, prnt): + self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0), + size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) + self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2 * len(CFILE_PARTS) + 1, vgap=0) + self.MainSizer.AddGrowableCol(0) + for idx, (name, panel_class) in enumerate(CFILE_PARTS): + button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name, + label=name, bitmap=GetCollapsedIconBitmap(), parent=self.Editor, pos=wx.Point(0, 0), + size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT) + button.SetBitmapSelected(GetExpandedIconBitmap()) + button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id) + self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW) + if panel_class == VariablesEditor: + panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler) + panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler) + self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW) + self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1} + self.Spacer = wx.Panel(self.Editor, -1) + self.SpacerExpanded = True + self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW) + self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS)) + self.Editor.SetSizer(self.MainSizer) + def __init__(self, parent, controler, window): + EditorPanel.__init__(self, parent, "", window, controler) + img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() + self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) + self.Controler.OnCloseEditor(self) + fullname = self.Controler.CTNFullName() + if not self.Controler.CFileIsSaved(): + return "~%s~" % fullname + def GetBufferState(self): + return self.Controler.GetBufferState() + self.Controler.LoadPrevious() + self.Controler.LoadNext() + for infos in self.Panels.itervalues(): + infos["panel"].RefreshView() + def GenPanelButtonCallback(self, name): + def PanelButtonCallback(event): + return PanelButtonCallback + def ExpandPanel(self, name): + infos = self.Panels.get(name, None) + if infos is not None and not infos["expanded"]: + infos["expanded"] = True + infos["button"].SetToggle(True) + self.MainSizer.AddGrowableRow(infos["row"]) + self.RefreshSizerLayout() + def CollapsePanel(self, name): + infos = self.Panels.get(name, None) + if infos is not None and infos["expanded"]: + infos["expanded"] = False + infos["button"].SetToggle(False) + self.MainSizer.RemoveGrowableRow(infos["row"]) + self.RefreshSizerLayout() + def TogglePanel(self, name): + infos = self.Panels.get(name, None) + infos["expanded"] = not infos["expanded"] + infos["button"].SetToggle(infos["expanded"]) + self.MainSizer.AddGrowableRow(infos["row"]) + self.MainSizer.RemoveGrowableRow(infos["row"]) + self.RefreshSizerLayout() + def RefreshSizerLayout(self): + for infos in self.Panels.itervalues(): + expand_spacer = expand_spacer and not infos["expanded"] + if self.SpacerExpanded != expand_spacer: + self.SpacerExpanded = expand_spacer + self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS)) + self.MainSizer.RemoveGrowableRow(2 * len(CFILE_PARTS)) + self.MainSizer.Layout() --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/README Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/__init__.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/c_ext.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,315 @@
+from xml.dom import minidom +from ConfigTree import ConfigTreeNode, opjimg +from CFileEditor import CFileEditor +from PLCControler import PLCControler, UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY +CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd")) +TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", + "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L", + "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"} + XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> + <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="CExtension"> + <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/> + <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/> + EditorType = CFileEditor + filepath = self.CFileName() + self.CFile = CFileClasses["CFile"]() + if os.path.isfile(filepath): + xmlfile = open(filepath, 'r') + tree = minidom.parse(xmlfile) + for child in tree.childNodes: + if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile": + self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) + self.CreateCFileBuffer(True) + self.CreateCFileBuffer(False) + return os.path.join(self.CTNPath(), "cfile.xml") + def GetBaseTypes(self): + return self.GetCTRoot().GetBaseTypes() + def GetDataTypes(self, basetypes = False, only_locatables = False): + return self.GetCTRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables) + def GetSizeOfType(self, type): + return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None) + def SetVariables(self, variables): + self.CFile.variables.setvariable([]) + variable = CFileClasses["variables_variable"]() + variable.setname(var["Name"]) + variable.settype(var["Type"]) + variable.setclass(var["Class"]) + self.CFile.variables.appendvariable(variable) + def GetVariables(self): + for var in self.CFile.variables.getvariable(): + datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()}) + def GetVariableLocationTree(self): + '''See ConfigTreeNode.GetVariableLocationTree() for a description.''' + current_location = ".".join(map(str, self.GetCurrentLocation())) + input = memory = output = 0 + for var in self.CFile.variables.getvariable(): + var_size = self.GetSizeOfType(var.gettype()) + if var.getclass() == "input": + var_class = LOCATION_VAR_INPUT + if var_size is not None: + var_location = "%%I%s%s.%d"%(var_size, current_location, input) + elif var.getclass() == "memory": + var_class = LOCATION_VAR_INPUT + if var_size is not None: + var_location = "%%M%s%s.%d"%(var_size, current_location, memory) + var_class = LOCATION_VAR_OUTPUT + if var_size is not None: + var_location = "%%Q%s%s.%d"%(var_size, current_location, output) + vars.append({"name": var.getname(), + "IEC_type": var.gettype(), + "var_name": var.getname(), + "location": var_location, + return {"name": self.BaseParams.getName(), + "type": LOCATION_CONFNODE, + "location": self.GetFullIEC_Channel(), + def SetPartText(self, name, text): + self.CFile.includes.settext(text) + elif name == "Globals": + self.CFile.globals.settext(text) + self.CFile.initFunction.settext(text) + elif name == "CleanUp": + self.CFile.cleanUpFunction.settext(text) + elif name == "Retrieve": + self.CFile.retrieveFunction.settext(text) + elif name == "Publish": + self.CFile.publishFunction.settext(text) + def GetPartText(self, name): + return self.CFile.includes.gettext() + elif name == "Globals": + return self.CFile.globals.gettext() + return self.CFile.initFunction.gettext() + elif name == "CleanUp": + return self.CFile.cleanUpFunction.gettext() + elif name == "Retrieve": + return self.CFile.retrieveFunction.gettext() + elif name == "Publish": + return self.CFile.publishFunction.gettext() + {"bitmap" : os.path.join("images", "EditCfile"), + "name" : _("Edit C File"), + "tooltip" : _("Edit C File"), + "method" : "_OpenView"}, + def CTNTestModified(self): + return self.ChangesToSave or not self.CFileIsSaved() + filepath = self.CFileName() + text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" + extras = {"xmlns":"http://www.w3.org/2001/XMLSchema", + "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance", + "xsi:schemaLocation" : "cext_xsd.xsd"} + text += self.CFile.generateXMLText("CFile", 0, extras) + xmlfile = open(filepath,"w") + xmlfile.write(text.encode("utf-8")) + self.MarkCFileAsSaved() + def CTNGenerate_C(self, buildpath, locations): + @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(str, current_location)) + text = "/* Code generated by Beremiz c_ext confnode */\n\n" + text += "/* User includes */\n" + text += self.CFile.includes.gettext() + text += """/* Beremiz c_ext confnode includes */ + #include "iec_std_lib.h" + inputs = memories = outputs = 0 + for variable in self.CFile.variables.variable: + var = {"Name" : variable.getname(), "Type" : variable.gettype()} + if variable.getclass() == "input": + var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs) + elif variable.getclass() == "memory": + var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories) + var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs) + text += "/* Beremiz c_ext confnode user variables definition */\n" + base_types = self.GetCTRoot().GetBaseTypes() + if var["Type"] in base_types: + text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"]) + text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"]) + text += "/* User variables reference */\n" + text += "#define %s beremiz%s\n"%(var["Name"], var["location"]) + # Adding user global variables and routines + text += "/* User internal user variables and routines */\n" + text += self.CFile.globals.gettext() + # Adding Beremiz confnode functions + text += "/* Beremiz confnode functions */\n" + text += "int __init_%s(int argc,char **argv)\n{\n"%location_str + text += self.CFile.initFunction.gettext() + text += "void __cleanup_%s(void)\n{\n"%location_str + text += self.CFile.cleanUpFunction.gettext() + text += "void __retrieve_%s(void)\n{\n"%location_str + text += self.CFile.retrieveFunction.gettext() + text += "void __publish_%s(void)\n{\n"%location_str + text += self.CFile.publishFunction.gettext() + Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str) + cfile = open(Gen_Cfile_path,'w') + matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()) + return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True +#------------------------------------------------------------------------------- +# Current Buffering Management Functions +#------------------------------------------------------------------------------- + Return a copy of the cfile model + return cPickle.loads(cPickle.dumps(model)) + def CreateCFileBuffer(self, saved): + self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved) + self.CFileBuffer.Buffering(cPickle.dumps(self.CFile)) + def StartBuffering(self): + def EndBuffering(self): + self.CFileBuffer.Buffering(cPickle.dumps(self.CFile)) + def MarkCFileAsSaved(self): + self.CFileBuffer.CurrentSaved() + def CFileIsSaved(self): + return self.CFileBuffer.IsCurrentSaved() and not self.Buffering + def LoadPrevious(self): + self.CFile = cPickle.loads(self.CFileBuffer.Previous()) + self.CFile = cPickle.loads(self.CFileBuffer.Next()) + def GetBufferState(self): + first = self.CFileBuffer.IsFirst() and not self.Buffering + last = self.CFileBuffer.IsLast() + return not first, not last + CTNChildrenTypes = [("C_File",_Cfile, "C file")] + def CTNGenerate_C(self, buildpath, locations): --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/cext_xsd.xsd Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?> +<xsd:schema targetNamespace="cext_xsd.xsd" + xmlns:cext="cext_xsd.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> + <xsd:element name="CFile"> + <xsd:element name="includes" type="cext:CCode"/> + <xsd:element name="variables"> + <xsd:element name="variable" minOccurs="0" maxOccurs="unbounded"> + <xsd:attribute name="name" type="xsd:string" use="required"/> + <xsd:attribute name="type" type="xsd:string" use="required"/> + <xsd:attribute name="class" use="required"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="input"/> + <xsd:enumeration value="memory"/> + <xsd:enumeration value="output"/> + <xsd:element name="globals" type="cext:CCode"/> + <xsd:element name="initFunction" type="cext:CCode"/> + <xsd:element name="cleanUpFunction" type="cext:CCode"/> + <xsd:element name="retrieveFunction" type="cext:CCode"/> + <xsd:element name="publishFunction" type="cext:CCode"/> + <xsd:complexType name="CCode"> + <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation> + <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/.cvsignore Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/NetworkEditor.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,122 @@
+base_folder = os.path.split(sys.path[0])[0] +CanFestivalPath = os.path.join(base_folder, "CanFestival-3") +from subindextable import EditingPanel +from networkedit import NetworkEditorTemplate +from controls import EditorPanel +] = [wx.NewId() for _init_ctrls in range(1)] +[ID_NETWORKEDITORCONFNODEMENUADDSLAVE, ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, + ID_NETWORKEDITORCONFNODEMENUMASTER, +] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(3)] +[ID_NETWORKEDITORMASTERMENUNODEINFOS, ID_NETWORKEDITORMASTERMENUDS301PROFILE, + ID_NETWORKEDITORMASTERMENUDS302PROFILE, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, + ID_NETWORKEDITORMASTERMENUADD, +] = [wx.NewId() for _init_coll_MasterMenu_Items in range(5)] +[ID_NETWORKEDITORADDMENUSDOSERVER, ID_NETWORKEDITORADDMENUSDOCLIENT, + ID_NETWORKEDITORADDMENUPDOTRANSMIT, ID_NETWORKEDITORADDMENUPDORECEIVE, + ID_NETWORKEDITORADDMENUMAPVARIABLE, ID_NETWORKEDITORADDMENUUSERTYPE, +] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)] +class NetworkEditor(EditorPanel, NetworkEditorTemplate): + def _init_coll_MainSizer_Items(self, parent): + parent.AddWindow(self.NetworkNodes, 0, border=5, flag=wx.GROW|wx.ALL) + def _init_coll_MainSizer_Growables(self, parent): + parent.AddGrowableCol(0) + parent.AddGrowableRow(0) + def _init_sizers(self): + self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0) + self._init_coll_MainSizer_Items(self.MainSizer) + self._init_coll_MainSizer_Growables(self.MainSizer) + self.Editor.SetSizer(self.MainSizer) + def _init_Editor(self, prnt): + self.Editor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0), + size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) + NetworkEditorTemplate._init_ctrls(self, self.Editor) + def __init__(self, parent, controler, window): + EditorPanel.__init__(self, parent, "", window, controler) + NetworkEditorTemplate.__init__(self, controler, window, False) + img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() + self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) + self.RefreshNetworkNodes() + self.RefreshBufferState() + self.Controler.OnCloseEditor(self) + def GetConfNodeMenuItems(self): + add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_NETWORKEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)), + (wx.ITEM_NORMAL, (_('SDO Client'), ID_NETWORKEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)), + (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_NETWORKEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)), + (wx.ITEM_NORMAL, (_('PDO Receive'), ID_NETWORKEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)), + (wx.ITEM_NORMAL, (_('Map Variable'), ID_NETWORKEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)), + (wx.ITEM_NORMAL, (_('User Type'), ID_NETWORKEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))] + profile = self.Manager.GetCurrentProfileName() + if profile not in ("None", "DS-301"): + other_profile_text = _("%s Profile") % profile + add_menu.append((wx.ITEM_SEPARATOR, None)) + for text, indexes in self.Manager.GetCurrentSpecificMenu(): + add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text)))) + other_profile_text = _('Other Profile') + master_menu = [(wx.ITEM_NORMAL, (_('Node infos'), ID_NETWORKEDITORMASTERMENUNODEINFOS, '', self.OnNodeInfosMenu)), + (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_NETWORKEDITORMASTERMENUDS301PROFILE, '', self.OnCommunicationMenu)), + (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_NETWORKEDITORMASTERMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)), + (wx.ITEM_NORMAL, (other_profile_text, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)), + (wx.ITEM_SEPARATOR, None), + (add_menu, (_('Add'), ID_NETWORKEDITORMASTERMENUADD))] + return [(wx.ITEM_NORMAL, (_('Add slave'), ID_NETWORKEDITORCONFNODEMENUADDSLAVE, '', self.OnAddSlaveMenu)), + (wx.ITEM_NORMAL, (_('Remove slave'), ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, '', self.OnRemoveSlaveMenu)), + (wx.ITEM_SEPARATOR, None), + (master_menu, (_('Master'), ID_NETWORKEDITORCONFNODEMENUMASTER))] + def RefreshMainMenu(self): + def RefreshConfNodeMenu(self, confnode_menu): + confnode_menu.Enable(ID_NETWORKEDITORCONFNODEMENUMASTER, self.NetworkNodes.GetSelection() == 0) + fullname = self.Controler.CTNFullName() + if not self.Manager.CurrentIsSaved(): + return "~%s~" % fullname + self.RefreshCurrentIndexList() + def RefreshBufferState(self): + NetworkEditorTemplate.RefreshBufferState(self) + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshFileMenu() + self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshPageTitles() + def OnNodeSelectedChanged(self, event): + NetworkEditorTemplate.OnNodeSelectedChanged(self, event) + wx.CallAfter(self.ParentWindow.RefreshConfNodeMenu) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/README Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/SlaveEditor.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,83 @@
+base_folder = os.path.split(sys.path[0])[0] +CanFestivalPath = os.path.join(base_folder, "CanFestival-3") +from subindextable import EditingPanel +from nodeeditor import NodeEditorTemplate +from controls import EditorPanel +[ID_SLAVEEDITORCONFNODEMENUNODEINFOS, ID_SLAVEEDITORCONFNODEMENUDS301PROFILE, + ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, + ID_SLAVEEDITORCONFNODEMENUADD, +] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(5)] +[ID_SLAVEEDITORADDMENUSDOSERVER, ID_SLAVEEDITORADDMENUSDOCLIENT, + ID_SLAVEEDITORADDMENUPDOTRANSMIT, ID_SLAVEEDITORADDMENUPDORECEIVE, + ID_SLAVEEDITORADDMENUMAPVARIABLE, ID_SLAVEEDITORADDMENUUSERTYPE, +] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)] +class SlaveEditor(EditorPanel, NodeEditorTemplate): + def _init_Editor(self, prnt): + self.Editor = EditingPanel(prnt, self, self.Controler, self.Editable) + def __init__(self, parent, controler, window, editable=True): + self.Editable = editable + EditorPanel.__init__(self, parent, "", window, controler) + NodeEditorTemplate.__init__(self, controler, window, False) + img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() + self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) + self.Controler.OnCloseEditor(self) + def GetConfNodeMenuItems(self): + add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_SLAVEEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)), + (wx.ITEM_NORMAL, (_('SDO Client'), ID_SLAVEEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)), + (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_SLAVEEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)), + (wx.ITEM_NORMAL, (_('PDO Receive'), ID_SLAVEEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)), + (wx.ITEM_NORMAL, (_('Map Variable'), ID_SLAVEEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)), + (wx.ITEM_NORMAL, (_('User Type'), ID_SLAVEEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))] + profile = self.Controler.GetCurrentProfileName() + if profile not in ("None", "DS-301"): + other_profile_text = _("%s Profile") % profile + add_menu.append((wx.ITEM_SEPARATOR, None)) + for text, indexes in self.Manager.GetCurrentSpecificMenu(): + add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text)))) + other_profile_text = _('Other Profile') + return [(wx.ITEM_NORMAL, (_('Node infos'), ID_SLAVEEDITORCONFNODEMENUNODEINFOS, '', self.OnNodeInfosMenu)), + (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_SLAVEEDITORCONFNODEMENUDS301PROFILE, '', self.OnCommunicationMenu)), + (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)), + (wx.ITEM_NORMAL, (other_profile_text, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)), + (wx.ITEM_SEPARATOR, None), + (add_menu, (_('Add'), ID_SLAVEEDITORCONFNODEMENUADD))] + def RefreshConfNodeMenu(self, confnode_menu): + confnode_menu.Enable(ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, False) + fullname = self.Controler.CTNFullName() + if not self.Controler.CurrentIsSaved(): + return "~%s~" % fullname + self.Editor.RefreshIndexList() + def RefreshCurrentIndexList(self): + def RefreshBufferState(self): + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshFileMenu() + self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshPageTitles() --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/__init__.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+from canfestival import * --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/canfestival.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,484 @@
+base_folder = os.path.split(sys.path[0])[0] +CanFestivalPath = os.path.join(base_folder, "CanFestival-3") +sys.path.append(os.path.join(CanFestivalPath, "objdictgen")) +from nodelist import NodeList +from nodemanager import NodeManager +import config_utils, gen_cfile, eds_utils +from networkedit import networkedit +from objdictedit import objdictedit +import canfestival_config as local_canfestival_config +from ConfigTree import ConfigTreeNode +from commondialogs import CreateNodeDialog +from SlaveEditor import SlaveEditor +from NetworkEditor import NetworkEditor +from gnosis.xml.pickle import * +from gnosis.xml.pickle.util import setParanoia +if wx.Platform == '__WXMSW__': + "CAN_Driver": "can_tcp_win32", + "CAN_Device": "127.0.0.1", + "CAN_Baudrate": "125K", + "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so", + "CAN_Baudrate": "125K", +#-------------------------------------------------- +#-------------------------------------------------- +class _SlaveCTN(NodeManager): + XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> + <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="CanFestivalSlaveNode"> + <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/> + <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/> + <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Slave_NodeId)d"/> + <xsd:attribute name="Sync_Align" type="xsd:integer" use="optional" default="0"/> + <xsd:attribute name="Sync_Align_Ratio" use="optional" default="50"> + <xsd:restriction base="xsd:integer"> + <xsd:minInclusive value="1"/> + <xsd:maxInclusive value="99"/> + EditorType = SlaveEditor + # TODO change netname when name change + NodeManager.__init__(self) + odfilepath = self.GetSlaveODPath() + if(os.path.isfile(odfilepath)): + self.OpenFileInCurrent(odfilepath) + dialog = CreateNodeDialog(None, wx.OK) + dialog.Type.Enable(False) + dialog.GenSYNC.Enable(False) + if dialog.ShowModal() == wx.ID_OK: + name, id, nodetype, description = dialog.GetValues() + profile, filepath = dialog.GetProfile() + NMT = dialog.GetNMTManagement() + options = dialog.GetOptions() + self.CreateNewNode(name, # Name - will be changed at build time + id, # NodeID - will be changed at build time + description,# description + filepath, # prfile filepath + self.CreateNewNode("SlaveNode", # Name - will be changed at build time + 0x00, # NodeID - will be changed at build time + def GetSlaveODPath(self): + return os.path.join(self.CTNPath(), 'slave.od') + def GetCanDevice(self): + return self.CanFestivalSlaveNode.getCan_Device() + ConfigTreeNode._OpenView(self) + if self._View is not None: + self._View.SetBusId(self.GetCurrentLocation()) + {"bitmap" : os.path.join("images", "NetworkEdit"), + "tooltip" : "Edit CanOpen slave with ObjdictEdit", + "method" : "_OpenView"}, + def CTNTestModified(self): + return self.ChangesToSave or self.OneFileHasChanged() + return self.SaveCurrentInFile(self.GetSlaveODPath()) + def SetParamsAttribute(self, path, value): + result = ConfigTreeNode.SetParamsAttribute(self, path, value) + # Filter IEC_Channel and Name, that have specific behavior + if path == "BaseParams.IEC_Channel" and self._View is not None: + self._View.SetBusId(self.GetCurrentLocation()) + def CTNGenerate_C(self, buildpath, locations): + @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 + prefix = "_".join(map(str, current_location)) + Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix ) + # Create a new copy of the model + slave = self.GetCurrentNodeCopy() + slave.SetNodeName("OD_%s"%prefix) + # allow access to local OD from Slave PLC + pointers = config_utils.LocalODPointers(locations, current_location, slave) + res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers) + res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave) + return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False + def LoadPrevious(self): + self.LoadCurrentPrevious() + def GetBufferState(self): + return self.GetCurrentBufferState() +#-------------------------------------------------- +#-------------------------------------------------- +class MiniNodeManager(NodeManager): + def __init__(self, parent, filepath, fullname): + NodeManager.__init__(self) + self.OpenFileInCurrent(filepath) + self.Fullname = fullname + def OnCloseEditor(self, view): + self.Parent.OnCloseEditor(view) + def GetBufferState(self): + return self.GetCurrentBufferState() +class _NodeListCTN(NodeList): + XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> + <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="CanFestivalNode"> + <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/> + <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/> + <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Master_NodeId)d"/> + <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/> + EditorType = NetworkEditor + manager = NodeManager() + NodeList.__init__(self, manager) + self.LoadProject(self.CTNPath()) + self.SetNetworkName(self.BaseParams.getName()) + def GetCanDevice(self): + return self.CanFestivalNode.getCan_Device() + def SetParamsAttribute(self, path, value): + result = ConfigTreeNode.SetParamsAttribute(self, path, value) + # Filter IEC_Channel and Name, that have specific behavior + if path == "BaseParams.IEC_Channel" and self._View is not None: + self._View.SetBusId(self.GetCurrentLocation()) + elif path == "BaseParams.Name": + self.SetNetworkName(value) + ConfigTreeNode._OpenView(self) + if self._View is not None: + self._View.SetBusId(self.GetCurrentLocation()) + def _ShowMasterGenerated(self): + if self._GeneratedView is None: + buildpath = self._getBuildPath() + # Eventually create build dir + if not os.path.exists(buildpath): + self.GetCTRoot().logger.write_error(_("Error: No PLC built\n")) + masterpath = os.path.join(buildpath, "MasterGenerated.od") + if not os.path.exists(masterpath): + self.GetCTRoot().logger.write_error(_("Error: No Master generated\n")) + app_frame = self.GetCTRoot().AppFrame + manager = MiniNodeManager(self, masterpath, self.CTNFullName() + ".generated_master") + self._GeneratedView = SlaveEditor(app_frame.TabsOpened, manager, app_frame, False) + app_frame.EditProjectElement(self._GeneratedView, "MasterGenerated") + def _CloseGenerateView(self): + if self._GeneratedView is not None: + app_frame = self.GetCTRoot().AppFrame + if app_frame is not None: + app_frame.DeletePage(self._GeneratedView) + {"bitmap" : os.path.join("images", "NetworkEdit"), + "name" : _("Edit network"), + "tooltip" : _("Edit CanOpen Network with NetworkEdit"), + "method" : "_OpenView"}, + {"bitmap" : os.path.join("images", "ShowMaster"), + "name" : _("Show Master"), + "tooltip" : _("Show Master generated by config_utils"), + "method" : "_ShowMasterGenerated"} + def OnCloseEditor(self, view): + ConfigTreeNode.OnCloseEditor(self, view) + if self._GeneratedView == view: + self._GeneratedView = None + ConfigTreeNode.OnCTNClose(self) + self._CloseGenerateView() + def CTNTestModified(self): + return self.ChangesToSave or self.HasChanged() + self.SetRoot(self.CTNPath()) + return self.SaveProject() is None + def CTNGenerate_C(self, buildpath, locations): + @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 + self._CloseGenerateView() + current_location = self.GetCurrentLocation() + # define a unique name for the generated C file + prefix = "_".join(map(str, current_location)) + Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix ) + # Create a new copy of the model with DCF loaded with PDO mappings for desired location + master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix) + except config_utils.PDOmappingException, e: + raise Exception, e.message + res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers) + file = open(os.path.join(buildpath, "MasterGenerated.od"), "w") + return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False + def LoadPrevious(self): + self.Manager.LoadCurrentPrevious() + self.Manager.LoadCurrentNext() + def GetBufferState(self): + return self.Manager.GetCurrentBufferState() + XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> + <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="CanFestivalInstance"> + <xsd:attribute name="CAN_Driver" type="xsd:string" use="optional" default="%(CAN_Driver)s"/> + <xsd:attribute name="Debug_mode" type="xsd:boolean" use="optional" default="false"/> + CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"), + ("CanOpenSlave",_SlaveCTN, "CanOpen Slave")] + def GetParamsAttributes(self, path = None): + infos = ConfigTreeNode.GetParamsAttributes(self, path = None) + if element["name"] == "CanFestivalInstance": + for child in element["children"]: + if child["name"] == "CAN_Driver": + DLL_LIST= getattr(local_canfestival_config,"DLL_LIST",None) + if DLL_LIST is not None: + child["type"] = DLL_LIST + def GetCanDriver(self): + can_driver = self.CanFestivalInstance.getCAN_Driver() + if sys.platform == 'win32': + if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(can_driver + '_DEBUG.dll'))): + can_driver += '_DEBUG.dll' + def CTNGenerate_C(self, buildpath, locations): + format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())), + "candriver" : self.GetCanDriver(), + "nodes_send_sync" : "", + "nodes_proceed_sync" : "", + "slavebootup_register" : "", + "post_sync_register" : "", + for child in self.IECSortedChildren(): + childlocstr = "_".join(map(str,child.GetCurrentLocation())) + nodename = "OD_%s" % childlocstr + # Try to get Slave Node + child_data = getattr(child, "CanFestivalSlaveNode", None) + # Not a slave -> master + child_data = getattr(child, "CanFestivalNode") + format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n '%( + child_data.getNodeId()) + if child_data.getSync_TPDOs(): + format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename) + format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename) + # initialize and declare node boot status variables for post_SlaveBootup lookup + SlaveIDs = child.GetSlaveIDs() + # define post_SlaveBootup lookup functions + format_dict["slavebootups"] += ( + "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename)) + format_dict["slavebootups"] += ( + "int %s_slave_%d_booted = 0;\n"%(nodename, id)) + # define post_SlaveBootup lookup functions + format_dict["slavebootups"] += ( + "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n"%(nodename)+ + # one case per declared node, mark node as booted + format_dict["slavebootups"] += ( + " %s_slave_%d_booted = 1;\n"%(nodename, id)+ + format_dict["slavebootups"] += ( + # expression to test if all declared nodes booted + format_dict["slavebootups"] += " && ".join(["%s_slave_%d_booted"%(nodename, id) for id in SlaveIDs]) + format_dict["slavebootups"] += " )\n" + ( + " Master_post_SlaveBootup(d,nodeId);\n"+ + # register previously declared func as post_SlaveBootup callback for that node + format_dict["slavebootup_register"] += ( + "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n"%(nodename,nodename)) + align = child_data.getSync_Align() + align_ratio=child_data.getSync_Align_Ratio() + format_dict["post_sync"] += ( + "static int %s_CalCount = 0;\n"%(nodename)+ + "static void %s_post_sync(CO_Data* d){\n"%(nodename)+ + " if(%s_CalCount < %d){\n"%(nodename, align)+ + " %s_CalCount++;\n"%(nodename)+ + " align_tick(%d);\n"%(align_ratio)+ + format_dict["post_sync_register"] += ( + "%s_Data.post_sync = %s_post_sync;\n"%(nodename,nodename)) + format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n '%( + child_data.getNodeId()) + # Include generated OD headers + format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename) + # Declare CAN channels according user filled config + format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%( + child_data.getCAN_Baudrate()) + format_dict["nodes_open"] += 'NODE_OPEN(%s)\n '%(nodename) + format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n '%(nodename) + format_dict["nodes_stop"] += 'NODE_STOP(%s)\n '%(nodename) + filename = os.path.join(os.path.split(__file__)[0],"cf_runtime.c") + cf_main = open(filename).read() % format_dict + cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict) + f = open(cf_main_path,'w') + return [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/cf_runtime.c Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,150 @@
+#include "canfestival.h" +/* CanFestival nodes generated OD headers*/ +#define BOARD_DECL(nodename, busname, baudrate)\ + s_BOARD nodename##Board = {busname, baudrate}; +/* CAN channels declaration */ +/* Keep track of init level to cleanup correctly */ +static int init_level=0; +/* Retrieve PLC cycle time */ +extern int common_ticktime__; +/* Called once all NetworkEdit declares slaves have booted*/ +static void Master_post_SlaveBootup(CO_Data* d, UNS8 nodeId) + /* Put the master in operational mode */ + setState(d, Operational); + /* Ask slave node to go in operational mode */ + masterSendNMTstateChange (d, 0, NMT_Start_Node); +/* Per master node slavebootup callbacks. Checks that + * every node have booted before calling Master_post_SlaveBootup */ +/* One slave node post_sync callback. + * Used to align PLC tick-time on CANopen SYNC +#define NODE_FORCE_SYNC(nodename) \ + /* Artificially force sync state to 1 so that it is not started */\ + nodename##_Data.CurrentCommunicationState.csSYNC = -1;\ + /* Force sync period to common_ticktime__ so that other node can read it*/\ + *nodename##_Data.COB_ID_Sync = 0x40000080;\ + *nodename##_Data.Sync_Cycle_Period = common_ticktime__ * 1000; +#define NODE_INIT(nodename, nodeid) \ + /* Defining the node Id */\ + setNodeId(&nodename##_Data, nodeid);\ + setState(&nodename##_Data, Initialisation); +#define NODE_MASTER_INIT(nodename, nodeid) \ + NODE_FORCE_SYNC(nodename) \ + NODE_INIT(nodename, nodeid) +#define NODE_SLAVE_INIT(nodename, nodeid) \ + NODE_INIT(nodename, nodeid) +void InitNodes(CO_Data* d, UNS32 id) + %(slavebootup_register)s +#define NODE_STOP(nodename) \ + masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\ + setState(&nodename##_Data, Stopped);\ +void Exit(CO_Data* d, UNS32 id) +#define NODE_CLOSE(nodename) \ + if(init_level_c-- > 0)\ + canClose(&nodename##_Data);\ +void __cleanup_%(locstr)s(void) + int init_level_c = init_level; +#define NODE_OPEN(nodename)\ + if(!canOpen(&nodename##Board,&nodename##_Data)){\ + fprintf(stderr,"Cannot open CAN intefrace %%s at speed %%s\n for CANopen node \"" #nodename "\"",nodename##Board.busname, nodename##Board.baudrate);\ +/*************************** INIT *****************************************/ +int __init_%(locstr)s(int argc,char **argv) +#ifndef NOT_USE_DYNAMIC_LOADING + if( !LoadCanDriver("%(candriver)s") ){ + fprintf(stderr, "Cannot load CAN interface library for CanFestival (%(candriver)s)\n");\ + StartTimerLoop(&InitNodes); +#define NODE_SEND_SYNC(nodename)\ + sendSYNCMessage(&nodename##_Data); +void __retrieve_%(locstr)s(void) + /* Locks the stack, so that no changes occurs while PLC access variables + * TODO : implement buffers to avoid such a big lock +#define NODE_PROCEED_SYNC(nodename)\ + proceedSYNC(&nodename##_Data); +void __publish_%(locstr)s(void) + /* Process sync event */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/config_utils.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,737 @@
+#This file is part of Beremiz, a Integrated Development Environment for +#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. +#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD +#See COPYING file for copyrights details. +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#General Public License for more details. +#You should have received a copy of the GNU General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Translation between IEC types and Can Open types +IECToCOType = {"BOOL":0x01, "SINT":0x02, "INT":0x03,"DINT":0x04,"LINT":0x10, + "USINT":0x05,"UINT":0x06,"UDINT":0x07,"ULINT":0x1B,"REAL":0x08, + "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07, + "LWORD":0x1B,"WSTRING":0x0B} +# Constants for PDO types +SlavePDOType = {"I" : TPDO, "Q" : RPDO} +InvertPDOType = {RPDO : TPDO, TPDO : RPDO} +PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800} +PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180} +VariableIncrement = 0x100 +VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000} +VariableDirText = {TPDO : "__I", RPDO : "__Q"} +VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6))) +TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)] +#------------------------------------------------------------------------------- +# Specific exception for PDO mapping errors +#------------------------------------------------------------------------------- +class PDOmappingException(Exception): +def LE_to_BE(value, size): + Convert Little Endian to Big Endian + @param value: value expressed in integer + @param size: number of bytes generated + @return: a string containing the value converted + data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value + list_car = [data[i:i+2] for i in xrange(0, len(data), 2)] + return "".join([chr(int(car, 16)) for car in list_car]) +def GetNodePDOIndexes(node, type, parameters = False): + Find the PDO indexes of a node + @param type: type of PDO searched (RPDO or TPDO or both) + @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False) + @return: a list of indexes found + indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF]) + indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF]) + return [idx + 0x200 for idx in indexes] +def SearchNodePDOMapping(loc_infos, node): + Find the PDO indexes of a node + @param type: type of PDO searched (RPDO or TPDO or both) + @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False) + @return: a list of indexes found + model = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + for PDOidx in GetNodePDOIndexes(node, loc_infos["pdotype"]): + values = node.GetEntry(PDOidx) + for subindex, mapping in enumerate(values): + if subindex != 0 and mapping & 0xFFFFFF00 == model: + return PDOidx, subindex +def GeneratePDOMappingDCF(idx, cobid, transmittype, pdomapping): + Build concise DCF value for configuring a PDO + @param idx: index of PDO parameters + @param cobid: PDO generated COB ID + @param transmittype : PDO transmit type + @param pdomapping: list of PDO mappings + @return: a tuple of value and number of parameters to add to DCF + # Create entry for RPDO or TPDO parameters and Disable PDO + dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x80000000 + cobid, 4) + # Set Transmit type synchrone + dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1) + # ---- INDEX ----- --- SUBINDEX ---- ----- SIZE ------ ------ DATA ------ + dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4) + if len(pdomapping) > 0: + dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(0x00, 1) + LE_to_BE(0x01, 4) + LE_to_BE(len(pdomapping), 1) + for subindex, (name, loc_infos) in enumerate(pdomapping): + value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"] + dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4) + return dcfdata, nbparams +class ConciseDCFGenerator: + def __init__(self, nodelist, nodename): + # Dictionary of location informations classed by name + # Dictionary of location that have not been mapped yet + self.LocationsNotMapped = {} + # Dictionary of location informations classed by name + self.MasterMapping = {} + # List of COB IDs available + self.ListCobIDAvailable = range(0x180, 0x580) + # Dictionary of mapping value where unexpected variables are stored + self.TrashVariables = {} + # Dictionary of pointed variables + self.PointedVariables = {} + self.NodeList = nodelist + self.Manager = self.NodeList.Manager + self.MasterNode = self.Manager.GetCurrentNodeCopy() + self.MasterNode.SetNodeName(nodename) + self.PrepareMasterNode() + def GetPointedVariables(self): + return self.PointedVariables + def RemoveUsedNodeCobId(self, node): + Remove all PDO COB ID used by the given node from the list of available COB ID + @return: a tuple of number of RPDO and TPDO for the node + # Get list of all node TPDO and RPDO indexes + nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True) + nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True) + # Mark all the COB ID of the node already mapped PDO as not available + for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes: + pdo_cobid = node.GetEntry(PdoIdx, 0x01) + # Extract COB ID, if PDO isn't active + pdo_cobid -= 0x80000000 + # Remove COB ID from the list of available COB ID + if pdo_cobid in self.ListCobIDAvailable: + self.ListCobIDAvailable.remove(pdo_cobid) + return len(nodeRpdoIndexes), len(nodeTpdoIndexes) + def PrepareMasterNode(self): + Add mandatory entries for DCF generation into MasterNode. + # Adding DCF entry into Master node + if not self.MasterNode.IsEntry(0x1F22): + self.MasterNode.AddEntry(0x1F22, 1, "") + self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode) + # Adding trash mappable variables for unused mapped datas + idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID() + # Add an entry for storing unexpected all variable + self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode) + for subidx, (size, typeidx) in enumerate(TrashVariables): + # Add a subentry for storing unexpected variable of this size + self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode) + self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode) + # Store the mapping value for this entry + self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size + RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode) + # Store the indexes of the first RPDO and TPDO available for MasterNode + self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber} + # Prepare MasterNode with all nodelist slaves + for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()): + node = nodeinfos["Node"] + RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node) + # Get Slave's default SDO server parameters + RSDO_cobid = node.GetEntry(0x1200,0x01) + RSDO_cobid = 0x600 + nodeid + TSDO_cobid = node.GetEntry(0x1200,0x02) + TSDO_cobid = 0x580 + nodeid + # Configure Master's SDO parameters entries + self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode) + self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid) + self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid) + self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid) + def GetMasterNode(self): + def AddParamsToDCF(self, nodeid, data, nbparams): + Add entry to DCF, for the requested nodeID + @param nodeid: id of the slave (int) + @param data: data to add to slave DCF (string) + @param nbparams: number of params added to slave DCF (int) + # Get current DCF for slave + nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid) + # Extract data and number of params in current DCF + if nodeDCF != None and nodeDCF != '': + tmpnbparams = [i for i in nodeDCF[:4]] + nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16) + data = nodeDCF[4:] + data + dcf = LE_to_BE(nbparams, 0x04) + data + # Set new DCF for slave + self.MasterNode.SetEntry(0x1F22, nodeid, dcf) + def GetEmptyPDO(self, nodeid, pdotype, start_index=None): + Search a not configured PDO for a slave + @param node: the slave node object + @param pdotype: type of PDO to generated (RPDO or TPDO) + @param start_index: Index where search must start (default: None) + @return tuple of PDO index, COB ID and number of subindex defined + # If no start_index defined, start with PDOtype base index + if start_index is None: + index = PDOTypeBaseIndex[pdotype] + # Search for all PDO possible index until find a configurable PDO + # starting from start_index + while index < PDOTypeBaseIndex[pdotype] + 0x200: + values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200) + if values != None and values[0] > 0: + # Check that all subindex upper than 0 equal 0 => configurable PDO + if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True): + cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1) + # If no COB ID defined in PDO, generate a new one (not used) + if len(self.ListCobIDAvailable) == 0: + # Calculate COB ID from standard values + if index < PDOTypeBaseIndex[pdotype] + 4: + cobid = PDOTypeBaseCobId[pdotype] + 0x100 * (index - PDOTypeBaseIndex[pdotype]) + nodeid + if cobid not in self.ListCobIDAvailable: + cobid = self.ListCobIDAvailable.pop(0) + return index, cobid, values[0] + def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs): + Record a new mapping request for a slave, and add related slave config to the DCF + @param nodeid: id of the slave (int) + @param pdotype: type of PDO to generated (RPDO or TPDO) + @param pdomapping: list od variables to map with PDO + # Add an entry to MasterMapping + self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], + "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]} + # Return the data to add to DCF + return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping) + return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping) + def GenerateDCF(self, locations, current_location, sync_TPDOs): + Generate Concise DCF of MasterNode for the locations list given + @param locations: list of locations to be mapped + @param current_location: tuple of the located prefixes not to be considered + @param sync_TPDOs: indicate if TPDO must be synchronous + #------------------------------------------------------------------------------- + # Verify that locations correspond to real slave variables + #------------------------------------------------------------------------------- + # Get list of locations check if exists and mappables -> put them in IECLocations + for location in locations: + COlocationtype = IECToCOType[location["IEC_TYPE"]] + name = location["NAME"] + if name in self.IECLocations: + if self.IECLocations[name]["type"] != COlocationtype: + raise PDOmappingException, _("Type conflict for location \"%s\"") % name + # Get only the part of the location that concern this node + loc = location["LOC"][len(current_location):] + # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) + if len(loc) not in (2, 3, 4): + raise PDOmappingException, _("Bad location size : %s") % str(loc) + direction = location["DIR"] + sizelocation = location["SIZE"] + # Extract and check nodeid + nodeid, index, subindex = loc[:3] + # Check Id is in slave node list + if nodeid not in self.NodeList.SlaveNodes.keys(): + raise PDOmappingException, _("Non existing node ID : %d (variable %s)") % (nodeid,name) + # Get the model for this node (made from EDS) + node = self.NodeList.SlaveNodes[nodeid]["Node"] + # Extract and check index and subindex + if not node.IsEntry(index, subindex): + raise PDOmappingException, _("No such index/subindex (%x,%x) in ID : %d (variable %s)") % (index,subindex,nodeid,name) + subentry_infos = node.GetSubentryInfos(index, subindex) + if subentry_infos and subentry_infos["pdo"]: + if sizelocation == "X" and len(loc) > 3: + elif sizelocation != "X" and len(loc) > 3: + raise PDOmappingException, _("Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex) + if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype: + raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name) + typeinfos = node.GetEntryInfos(COlocationtype) + self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction], + "nodeid": nodeid, "index": index,"subindex": subindex, + "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation} + raise PDOmappingException, _("Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex) + #------------------------------------------------------------------------------- + # Search for locations already mapped + #------------------------------------------------------------------------------- + for name, locationinfos in self.IECLocations.items(): + node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"] + # Search if slave has a PDO mapping this locations + result = SearchNodePDOMapping(locationinfos, node) + index, subindex = result + # Get COB ID of the PDO + cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1) + # Add PDO to MasterMapping + if cobid not in self.MasterMapping.keys(): + # Verify that PDO transmit type is conform to sync_TPDOs + transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2) + if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF: + # Change TransmitType to SYNCHRONE + data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, []) + # Change TransmitType to ASYCHRONE + data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, []) + # Add entry to slave dcf to change transmit type of + self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams) + values = node.GetEntry(index) + # Store the size of each entry mapped in PDO + for value in values[1:]: + mapping.append(value % 0x100) + self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping} + # Indicate that this PDO entry must be saved + if locationinfos["bit"] is not None: + if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType): + self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex] + if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]): + self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name) + self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name) + # Add location to those that haven't been mapped yet + if locationinfos["nodeid"] not in self.LocationsNotMapped.keys(): + self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []} + self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos)) + #------------------------------------------------------------------------------- + # Build concise DCF for the others locations + #------------------------------------------------------------------------------- + for nodeid, locations in self.LocationsNotMapped.items(): + node = self.NodeList.SlaveNodes[nodeid]["Node"] + # Initialize number of params and data to add to node DCF + # Generate the best PDO mapping for each type of PDO + for pdotype in (TPDO, RPDO): + if len(locations[pdotype]) > 0: + result = self.GetEmptyPDO(nodeid, pdotype) + raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid + pdoindex, pdocobid, pdonbparams = result + for name, loc_infos in locations[pdotype]: + pdosize += loc_infos["size"] + # If pdo's size > 64 bits + if pdosize > 64 or len(pdomapping) >= pdonbparams: + # Generate a new PDO Mapping + data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs) + nbparams += nbaddedparams + pdosize = loc_infos["size"] + pdomapping = [(name, loc_infos)] + result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1) + raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid + pdoindex, pdocobid, pdonbparams = result + pdomapping.append((name, loc_infos)) + # If there isn't locations yet but there is still a PDO to generate + if len(pdomapping) > 0: + # Generate a new PDO Mapping + data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs) + nbparams += nbaddedparams + # Add number of params and data to node DCF + self.AddParamsToDCF(nodeid, dataparams, nbparams) + #------------------------------------------------------------------------------- + # Master Node Configuration + #------------------------------------------------------------------------------- + # Generate Master's Configuration from informations stored in MasterMapping + for cobid, pdo_infos in self.MasterMapping.items(): + # Get next PDO index in MasterNode for this PDO type + current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]] + # Search if there is already a PDO in MasterNode with this cob id + for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True): + if self.MasterNode.GetEntry(idx, 1) == cobid: + # Add a PDO to MasterNode if not PDO have been found + if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]: + addinglist = [current_idx, current_idx + 0x200] + self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode) + self.MasterNode.SetEntry(current_idx, 0x01, cobid) + # Increment the number of PDO for this PDO type + self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1 + # Change the transmit type of the PDO + self.MasterNode.SetEntry(current_idx, 0x02, 0x01) + self.MasterNode.SetEntry(current_idx, 0x02, 0xFF) + for item in pdo_infos["mapping"]: + if isinstance(item, ListType): + # Add some subentries to PDO mapping if there is not enough + self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode) + # Generate MasterNode's PDO mapping + for subindex, variable in enumerate(mapping): + if isinstance(variable, (IntType, LongType)): + # If variable is an integer then variable is unexpected + self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable]) + typeidx, varname = variable + variable_infos = self.IECLocations[varname] + # Calculate base index for storing variable + mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \ + VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \ + variable_infos["nodeid"] + indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]], + variable_infos["sizelocation"], + '_'.join(map(str,current_location)), + variable_infos["nodeid"]) + # Search for an entry that has an empty subindex + while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: + if not self.MasterNode.IsEntry(mapvariableidx): + # Add entry to MasterNode + self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode) + nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00) + # Get Number of subentries already defined + nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00) + # if entry is full, go to next entry possible or stop now + if nbsubentries == 0xFF: + mapvariableidx += 8 * VariableIncrement + # Verify that a not full entry has been found + if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: + # Generate subentry name + if variable_infos["bit"] != None: + subindexname = "%(index)d_%(subindex)d_%(bit)d"%variable_infos + subindexname = "%(index)d_%(subindex)d"%variable_infos + # If entry have just been created, no subentry have to be added + self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode) + # Add informations to the new subentry created + self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname}) + self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx}) + # Set value of the PDO mapping + typeinfos = self.Manager.GetEntryInfos(typeidx) + value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"] + self.MasterNode.SetEntry(current_idx + 0x200, subindex, value) + # Add variable to pointed variables + self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname) +def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename): + Fills a CanFestival network editor model, with DCF with requested PDO mappings. + @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,...) + @param nodelist: CanFestival network editor model + @return: a modified copy of the given CanFestival network editor model + dcfgenerator = ConciseDCFGenerator(nodelist, nodename) + dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs) + masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables() + # allow access to local OD from Master PLC + pointers.update(LocalODPointers(locations, current_location, masternode)) + return masternode,pointers +def LocalODPointers(locations, current_location, slave): + for location in locations: + COlocationtype = IECToCOType[location["IEC_TYPE"]] + name = location["NAME"] + if name in IECLocations: + if IECLocations[name] != COlocationtype: + raise PDOmappingException, _("Type conflict for location \"%s\"") % name + # Get only the part of the location that concern this node + loc = location["LOC"][len(current_location):] + # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) + if len(loc) not in (2, 3, 4): + raise PDOmappingException, _("Bad location size : %s") % str(loc) + # Extract and check nodeid + index, subindex = loc[:2] + # Extract and check index and subindex + if not slave.IsEntry(index, subindex): + raise PDOmappingException, _("No such index/subindex (%x,%x) (variable %s)") % (index, subindex, name) + subentry_infos = slave.GetSubentryInfos(index, subindex) + if subentry_infos["type"] != COlocationtype: + raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name) + IECLocations[name] = COlocationtype + pointers[(index, subindex)] = name +if __name__ == "__main__": +Usage of config_utils.py test : + Displays help informations for config_utils + Reset the reference result of config_utils test. + Use with caution. Be sure that config_utils + is currently working properly. + # Boolean that indicate if reference result must be redefined + # Extract command options + opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"]) + except getopt.GetoptError: + # print help information and exit: + if o in ("-h", "--help"): + elif o in ("-r", "--reset"): + # Extract workspace base folder + base_folder = sys.path[0] + base_folder = os.path.split(base_folder)[0] + # Add CanFestival folder to search pathes + sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen")) + from nodemanager import * + # Open the test nodelist contained into test_config folder + manager = NodeManager() + nodelist = NodeList(manager) + result = nodelist.LoadProject("test_config") + # List of locations, we try to map for test + locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)}, + {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)}, + {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)}, + {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)}, + {"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24578_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24578,1)}, + {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)}, + {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)}, + {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)}, + {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)}, + {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}] + # Generate MasterNode configuration + masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode") + except ValueError, message: + print "%s\nTest Failed!"%message + # Get Text corresponding to MasterNode + result_node = masternode.PrintString() + result_vars = pprint.pformat(pointedvariables) + result = result_node + "\n********POINTERS*********\n" + result_vars + "\n" + # If reset has been choosen + # Write Text into reference result file + testfile = open("test_config/result.txt", "w") + print "Reset Successful!" + testfile = open("test_config/result_tmp.txt", "w") + os.system("diff test_config/result.txt test_config/result_tmp.txt") + os.remove("test_config/result_tmp.txt") --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/test_config/eds/PEAK MicroMod.eds Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1289 @@
+Description=PEAK MicroMod CANopenIA Generic +ModificationTime=05:05PM +ModificationDate=03-23-2005 +FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds +VendorName=PEAK System Technik +ProductName=PEAK MicroMod CANopenIA Generic +ProductNumber=0x00100000 +RevisionNumber=0x00010001 +DynamicChannelsSupported=0 +ParameterName=Device Type +ParameterName=Error Register +ParameterName=Identity Object +ParameterName=number of entries +ParameterName=Product Code +ParameterName=Revision number +ParameterName=PEAK Status Register +ParameterName=COB-ID SYNC +ParameterName=Manufacturer Device Name +ParameterName=Manufacturer Hardware Version +ParameterName=Manufacturer Software Version +ParameterName=Guard Time +ParameterName=Life Time Factor +ParameterName=Store Parameter Field +ParameterName=Number of Entries +ParameterName=Save all Parameters +ParameterName=Restore Default Parameters +ParameterName=Number of Entries +ParameterName=Restore all Default Parameters +ParameterName=Consumer Heartbeat Time +ParameterName=Number of Entries +ParameterName=Consumer Heartbeat Time +ParameterName=Consumer Heartbeat Time +ParameterName=Consumer Heartbeat Time +ParameterName=Producer Heartbeat Time +ParameterName=Verify Configuration +ParameterName=Number of entries +ParameterName=Configuration date +ParameterName=Configuration time +ParameterName=Receive PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x200 +ParameterName=Transmission Type +ParameterName=Receive PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x300 +ParameterName=Transmission Type +ParameterName=Receive PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x80000400 +ParameterName=Transmission Type +ParameterName=Receive PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x80000500 +ParameterName=Transmission Type +ParameterName=Receive PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=PDO Mapping Entry +ParameterName=Receive PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=Receive PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=Receive PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=Transmit PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x180 +ParameterName=Transmission Type +ParameterName=Inhibit Time +ParameterName=Event Timer +ParameterName=Transmit PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x280 +ParameterName=Transmission Type +ParameterName=Inhibit Time +ParameterName=Event Timer +ParameterName=Transmit PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x380 +ParameterName=Transmission Type +ParameterName=Inhibit Time +ParameterName=Event Timer +ParameterName=Transmit PDO Communication Parameter +ParameterName=Number of Entries +DefaultValue=$NODEID+0x80000480 +ParameterName=Transmission Type +ParameterName=Inhibit Time +ParameterName=Event Timer +ParameterName=Transmit PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=PDO Mapping Entry +ParameterName=Transmit PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=Transmit PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=PDO Mapping Entry +ParameterName=Transmit PDO Mapping Parameter +ParameterName=Number of Entries +ParameterName=Download Program Data +ParameterName=Number of elements +ParameterName=Download Program Data - HW Settings +ParameterName=Read Digital Input 8-bit +ParameterName=Number of Elements +ParameterName=DigInput8_1 +ParameterName=Polarity Digital Input +ParameterName=Number of Elements +ParameterName=Polarity8_1 +ParameterName=Write Digital Output 8-bit +ParameterName=Number of elements +ParameterName=DigOutput8_1 +ParameterName=Polarity Digital Output +ParameterName=Number of Elements +ParameterName=Polarity8_1 +ParameterName=Error Mode Digital Output +ParameterName=Number of elements +ParameterName=Error Mode 1 +ParameterName=Error Value Digital Output +ParameterName=Number of elements +ParameterName=Error Value 1 +ParameterName=Read Analog Input 16-bit +ParameterName=Number of elements +ParameterName=AnalogInput16_1 +ParameterName=AnalogInput16_2 +ParameterName=AnalogInput16_3 +ParameterName=AnalogInput16_4 +ParameterName=AnalogInput16_5 +ParameterName=AnalogInput16_6 +ParameterName=AnalogInput16_7 +ParameterName=AnalogInput16_8 +ParameterName=Write Analog Output 16-bit +ParameterName=Number of elements +ParameterName=AnalogOutput16_1 +ParameterName=AnalogOutput16_2 +ParameterName=AnalogOutput16_3 +ParameterName=AnalogOutput16_4 +ParameterName=Analog Input Global Interrupt +ParameterName=Analog Input Interrupt Delta +ParameterName=NrOfObjects +ParameterName=Analog Input Delta 1 +ParameterName=Analog Input Delta 2 +ParameterName=Analog Input Delta 3 +ParameterName=Analog Input Delta 4 +ParameterName=Analog Input Delta 5 +ParameterName=Analog Input Delta 6 +ParameterName=Analog Input Delta 7 +ParameterName=Analog Input Delta 8 +ParameterName=Error Mode Analog Output +ParameterName=Number of elements +ParameterName=Error Mode 1 +ParameterName=Error Mode 2 +ParameterName=Error Mode 3 +ParameterName=Error Mode 4 +ParameterName=Error Value Analog Output +ParameterName=Number of elements +ParameterName=Error Value 1 +ParameterName=Error Value 2 +ParameterName=Error Value 3 +ParameterName=Error Value 4 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/test_config/master.od Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,314 @@
+<!DOCTYPE PyObject SYSTEM "PyObjects.dtd"> +<PyObject module="node" class="Node" id="148584620"> +<attr name="Profile" type="dict" id="148589396" > +<attr name="Description" type="string" value="" /> +<attr name="Dictionary" type="dict" id="148592132" > + <key type="numeric" value="4096" /> + <val type="numeric" value="302" /> + <key type="numeric" value="4097" /> + <val type="numeric" value="0" /> + <key type="numeric" value="6144" /> + <val type="list" id="148585004" > + <item type="string" value="{True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4]" /> + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <key type="numeric" value="5120" /> + <val type="list" id="148586060" > + <item type="numeric" value="448" /> + <item type="numeric" value="1" /> + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <key type="numeric" value="4101" /> + <val type="numeric" value="1073741952" /> + <key type="numeric" value="4102" /> + <val type="numeric" value="50000" /> + <key type="numeric" value="8192" /> + <val type="numeric" value="0" /> + <key type="numeric" value="6656" /> + <val type="list" id="148585228" > + <item type="numeric" value="268501000" /> + <key type="numeric" value="5632" /> + <val type="list" id="148585036" > + <item type="numeric" value="536870920" /> + <key type="numeric" value="4120" /> + <val type="list" id="148585292" > + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <item type="numeric" value="0" /> + <key type="numeric" value="4118" /> + <val type="list" id="148585100" > + <item type="numeric" value="4195804" /> +<attr name="SpecificMenu" type="list" id="148584044" > +<attr name="ParamsDictionary" type="dict" id="148592268" > +<attr name="UserMapping" type="dict" id="148592404" > + <key type="numeric" value="8192" /> + <val type="dict" id="148592540" > + <key type="string" value="need" /> + <val type="False" value="" /> + <key type="string" value="values" /> + <val type="list" id="148585868" > + <item type="dict" id="148592676" > + <key type="string" value="access" /> + <val type="string" value="rw" /> + <key type="string" value="pdo" /> + <val type="True" value="" /> + <key type="string" value="type" /> + <val type="numeric" value="5" /> + <key type="string" value="name" /> + <val type="string">Read Inputs</val> + <key type="string" value="name" /> + <val type="string">Read Inputs</val> + <key type="string" value="struct" /> + <val type="numeric" value="1" /> +<attr name="DS302" type="dict" id="148592812" > + <key type="numeric" value="7968" /> + <val type="dict" id="148592948" > + <key type="string" value="need" /> + <val type="False" value="" /> + <key type="string" value="values" /> + <val type="list" id="148584684" > + <item type="dict" id="148593084" > + <key type="string" value="access" /> + <val type="string" value="ro" /> + <key type="string" value="pdo" /> + <val type="False" value="" /> + <key type="string" value="type" /> + <val type="numeric" value="5" /> + <key type="string" value="name" /> + <val type="string" value="Number of Entries" /> + <item type="dict" id="148593220" > + <key type="string" value="access" /> + <val type="string" value="rw" /> + <key type="string" value="pdo" /> + <val type="False" value="" /> + <key type="string" value="type" /> + <val type="numeric" value="15" /> + <key type="string" value="name" /> + <val type="string" value="Store DCF for node %d[(sub)]" /> + <key type="string" value="nbmax" /> + <val type="numeric" value="127" /> + <key type="string" value="name" /> + <val type="string" value="Store DCF" /> + <key type="string" value="struct" /> + <val type="numeric" value="7" /> + <key type="numeric" value="7969" /> + <val type="dict" id="148593356" > + <key type="string" value="need" /> + <val type="False" value="" /> + <key type="string" value="values" /> + <val type="list" id="148585516" > + <item type="dict" id="148593492" > + <key type="string" value="access" /> + <val type="string" value="ro" /> + <key type="string" value="pdo" /> + <val type="False" value="" /> + <key type="string" value="type" /> + <val type="numeric" value="5" /> + <key type="string" value="name" /> + <val type="string" value="Number of Entries" /> + <item type="dict" id="148593628" > + <key type="string" value="access" /> + <val type="string" value="rw" /> + <key type="string" value="pdo" /> + <val type="False" value="" /> + <key type="string" value="type" /> + <val type="numeric" value="2" /> + <key type="string" value="name" /> + <val type="string" value="Storage Format for Node %d[(sub)]" /> + <key type="string" value="nbmax" /> + <val type="numeric" value="127" /> + <key type="string" value="name" /> + <val type="string" value="Storage Format" /> + <key type="string" value="struct" /> + <val type="numeric" value="7" /> + <key type="numeric" value="7970" /> + <val type="dict" id="148593764" > + <key type="string" value="need" /> + <val type="False" value="" /> + <key type="string" value="values" /> + <val type="list" id="148594956" > + <item type="dict" id="148593900" > + <key type="string" value="access" /> + <val type="string" value="ro" /> + <key type="string" value="pdo" /> + <val type="False" value="" /> + <key type="string" value="type" /> + <val type="numeric" value="5" /> + <key type="string" value="name" /> + <val type="string" value="Number of Entries" /> + <item type="dict" id="148594036" > + <key type="string" value="access" /> + <val type="string" value="rw" /> + <key type="string" value="pdo" /> + <val type="False" value="" /> + <key type="string" value="type" /> + <val type="numeric" value="15" /> + <key type="string" value="name" /> + <val type="string" value="Concise DCF for Node %d[(sub)]" /> + <key type="string" value="nbmax" /> + <val type="numeric" value="127" /> + <key type="string" value="name" /> + <val type="string" value="Concise DCF" /> + <key type="string" value="struct" /> + <val type="numeric" value="7" /> +<attr name="ProfileName" type="string" value="None" /> +<attr name="Type" type="string">master</attr> +<attr name="ID" type="numeric" value="0" /> +<attr name="Name" type="string">TestMaster</attr> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/test_config/nodelist.cpj Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,7 @@
+Node64DCFName=PEAK MicroMod.eds --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/test_config/result.txt Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,257 @@
+1001 (Error Register): 0 +1005 (SYNC COB ID): 40000080 +1006 (Communication / Cycle Period): C350 +1016 (Consumer Heartbeat Time): +1016 01 (Consumer Heartbeat Time): 4005DC +1018 02 (Product Code): 0 +1018 03 (Revision Number): 0 +1018 04 (Serial Number): 0 +1280 (Client SDO 1 Parameter): +1280 01 (COB ID Client to Server (Transmit SDO)): 640 +1280 02 (COB ID Server to Client (Receive SDO)): 5C0 +1280 03 (Node ID of the SDO Server): 40 +1400 (Receive PDO 1 Parameter): +1400 01 (COB ID used by PDO): 1C0 +1400 02 (Transmission Type): 1 +1400 03 (Inhibit Time): 0 +1400 04 (Compatibility Entry): 0 +1400 05 (Event Timer): 0 +1401 (Receive PDO 2 Parameter): +1401 01 (COB ID used by PDO): 2C0 +1401 02 (Transmission Type): 1 +1401 03 (Inhibit Time): 0 +1401 04 (Compatibility Entry): 0 +1401 05 (Event Timer): 0 +1402 (Receive PDO 3 Parameter): +1402 01 (COB ID used by PDO): 182 +1402 02 (Transmission Type): 1 +1402 03 (Inhibit Time): 0 +1402 04 (Compatibility Entry): 0 +1402 05 (Event Timer): 0 +1403 (Receive PDO 4 Parameter): +1403 01 (COB ID used by PDO): 183 +1403 02 (Transmission Type): 1 +1403 03 (Inhibit Time): 0 +1403 04 (Compatibility Entry): 0 +1403 05 (Event Timer): 0 +1404 (Receive PDO 5 Parameter): +1404 01 (COB ID used by PDO): 181 +1404 02 (Transmission Type): 1 +1404 03 (Inhibit Time): 0 +1404 04 (Compatibility Entry): 0 +1404 05 (Event Timer): 0 +1600 (Receive PDO 1 Mapping): +1600 01 (PDO 1 Mapping for an application object 1): 22400108 +1600 02 (PDO 1 Mapping for an application object 2): 0 +1601 (Receive PDO 2 Mapping): +1601 01 (PDO 2 Mapping for an application object 1): 20000310 +1601 02 (PDO 2 Mapping for an application object 2): 23400110 +1601 03 (PDO 2 Mapping for an application object 3): 23400210 +1601 04 (PDO 2 Mapping for an application object 4): 20000310 +1602 (Receive PDO 3 Mapping): +1602 01 (PDO 3 Mapping for an application object 1): 24400120 +1602 02 (PDO 3 Mapping for an application object 2): 24400220 +1603 (Receive PDO 4 Mapping): +1603 01 (PDO 4 Mapping for an application object 1): 24400320 +1604 (Receive PDO 5 Mapping): +1604 01 (PDO 5 Mapping for an application object 1): 22400208 +1604 02 (PDO 5 Mapping for an application object 2): 24400420 +1800 (Transmit PDO 1 Parameter): +1800 01 (COB ID used by PDO): {True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4] +1800 02 (Transmission Type): 0 +1800 03 (Inhibit Time): 0 +1800 04 (Compatibility Entry): 0 +1800 05 (Event Timer): 0 +1801 (Transmit PDO 2 Parameter): +1801 01 (COB ID used by PDO): 340 +1801 02 (Transmission Type): 1 +1801 03 (Inhibit Time): 0 +1801 04 (Compatibility Entry): 0 +1801 05 (Event Timer): 0 +1A00 (Transmit PDO 1 Mapping): +1A00 01 (PDO 1 Mapping for a process data variable 1): 10010008 +1A01 (Transmit PDO 2 Mapping): +1A01 01 (PDO 2 Mapping for a process data variable 1): 43400110 +1A01 02 (PDO 2 Mapping for a process data variable 2): 20000310 +1A01 03 (PDO 2 Mapping for a process data variable 3): 20000310 +1A01 04 (PDO 2 Mapping for a process data variable 4): 20000310 +1F22 01 (Concise DCF for Node 1): +1F22 02 (Concise DCF for Node 2): +1F22 03 (Concise DCF for Node 3): +1F22 04 (Concise DCF for Node 4): +1F22 05 (Concise DCF for Node 5): +1F22 06 (Concise DCF for Node 6): +1F22 07 (Concise DCF for Node 7): +1F22 08 (Concise DCF for Node 8): +1F22 09 (Concise DCF for Node 9): +1F22 0A (Concise DCF for Node 10): +1F22 0B (Concise DCF for Node 11): +1F22 0C (Concise DCF for Node 12): +1F22 0D (Concise DCF for Node 13): +1F22 0E (Concise DCF for Node 14): +1F22 0F (Concise DCF for Node 15): +1F22 10 (Concise DCF for Node 16): +1F22 11 (Concise DCF for Node 17): +1F22 12 (Concise DCF for Node 18): +1F22 13 (Concise DCF for Node 19): +1F22 14 (Concise DCF for Node 20): +1F22 15 (Concise DCF for Node 21): +1F22 16 (Concise DCF for Node 22): +1F22 17 (Concise DCF for Node 23): +1F22 18 (Concise DCF for Node 24): +1F22 19 (Concise DCF for Node 25): +1F22 1A (Concise DCF for Node 26): +1F22 1B (Concise DCF for Node 27): +1F22 1C (Concise DCF for Node 28): +1F22 1D (Concise DCF for Node 29): +1F22 1E (Concise DCF for Node 30): +1F22 1F (Concise DCF for Node 31): +1F22 20 (Concise DCF for Node 32): +1F22 21 (Concise DCF for Node 33): +1F22 22 (Concise DCF for Node 34): +1F22 23 (Concise DCF for Node 35): +1F22 24 (Concise DCF for Node 36): +1F22 25 (Concise DCF for Node 37): +1F22 26 (Concise DCF for Node 38): +1F22 27 (Concise DCF for Node 39): +1F22 28 (Concise DCF for Node 40): +1F22 29 (Concise DCF for Node 41): +1F22 2A (Concise DCF for Node 42): +1F22 2B (Concise DCF for Node 43): +1F22 2C (Concise DCF for Node 44): +1F22 2D (Concise DCF for Node 45): +1F22 2E (Concise DCF for Node 46): +1F22 2F (Concise DCF for Node 47): +1F22 30 (Concise DCF for Node 48): +1F22 31 (Concise DCF for Node 49): +1F22 32 (Concise DCF for Node 50): +1F22 33 (Concise DCF for Node 51): +1F22 34 (Concise DCF for Node 52): +1F22 35 (Concise DCF for Node 53): +1F22 36 (Concise DCF for Node 54): +1F22 37 (Concise DCF for Node 55): +1F22 38 (Concise DCF for Node 56): +1F22 39 (Concise DCF for Node 57): +1F22 3A (Concise DCF for Node 58): +1F22 3B (Concise DCF for Node 59): +1F22 3C (Concise DCF for Node 60): +1F22 3D (Concise DCF for Node 61): +1F22 3E (Concise DCF for Node 62): +1F22 3F (Concise DCF for Node 63): +1F22 40 (Concise DCF for Node 64): 23 arg defined +1F22 40, arg 1: 1800 01 00000004 800001C0 +1F22 40, arg 2: 1800 02 00000001 01 +1F22 40, arg 3: 1800 01 00000004 000001C0 +1F22 40, arg 4: 1801 01 00000004 800002C0 +1F22 40, arg 5: 1801 02 00000001 01 +1F22 40, arg 6: 1801 01 00000004 000002C0 +1F22 40, arg 7: 1401 01 00000004 80000340 +1F22 40, arg 8: 1401 02 00000001 01 +1F22 40, arg 9: 1401 01 00000004 00000340 +1F22 40, arg 10: 1804 01 00000004 80000181 +1F22 40, arg 11: 1804 02 00000001 01 +1F22 40, arg 12: 1804 01 00000004 00000181 +1F22 40, arg 13: 1A04 01 00000004 60020108 +1F22 40, arg 14: 1A04 02 00000004 64260120 +1F22 40, arg 15: 1805 01 00000004 80000182 +1F22 40, arg 16: 1805 02 00000001 01 +1F22 40, arg 17: 1805 01 00000004 00000182 +1F22 40, arg 18: 1A05 01 00000004 64260220 +1F22 40, arg 19: 1A05 02 00000004 64260320 +1F22 40, arg 20: 1806 01 00000004 80000183 +1F22 40, arg 21: 1806 02 00000001 01 +1F22 40, arg 22: 1806 01 00000004 00000183 +1F22 40, arg 23: 1A06 01 00000004 64260420 +1F22 41 (Concise DCF for Node 65): +1F22 42 (Concise DCF for Node 66): +1F22 43 (Concise DCF for Node 67): +1F22 44 (Concise DCF for Node 68): +1F22 45 (Concise DCF for Node 69): +1F22 46 (Concise DCF for Node 70): +1F22 47 (Concise DCF for Node 71): +1F22 48 (Concise DCF for Node 72): +1F22 49 (Concise DCF for Node 73): +1F22 4A (Concise DCF for Node 74): +1F22 4B (Concise DCF for Node 75): +1F22 4C (Concise DCF for Node 76): +1F22 4D (Concise DCF for Node 77): +1F22 4E (Concise DCF for Node 78): +1F22 4F (Concise DCF for Node 79): +1F22 50 (Concise DCF for Node 80): +1F22 51 (Concise DCF for Node 81): +1F22 52 (Concise DCF for Node 82): +1F22 53 (Concise DCF for Node 83): +1F22 54 (Concise DCF for Node 84): +1F22 55 (Concise DCF for Node 85): +1F22 56 (Concise DCF for Node 86): +1F22 57 (Concise DCF for Node 87): +1F22 58 (Concise DCF for Node 88): +1F22 59 (Concise DCF for Node 89): +1F22 5A (Concise DCF for Node 90): +1F22 5B (Concise DCF for Node 91): +1F22 5C (Concise DCF for Node 92): +1F22 5D (Concise DCF for Node 93): +1F22 5E (Concise DCF for Node 94): +1F22 5F (Concise DCF for Node 95): +1F22 60 (Concise DCF for Node 96): +1F22 61 (Concise DCF for Node 97): +1F22 62 (Concise DCF for Node 98): +1F22 63 (Concise DCF for Node 99): +1F22 64 (Concise DCF for Node 100): +1F22 65 (Concise DCF for Node 101): +1F22 66 (Concise DCF for Node 102): +1F22 67 (Concise DCF for Node 103): +1F22 68 (Concise DCF for Node 104): +1F22 69 (Concise DCF for Node 105): +1F22 6A (Concise DCF for Node 106): +1F22 6B (Concise DCF for Node 107): +1F22 6C (Concise DCF for Node 108): +1F22 6D (Concise DCF for Node 109): +1F22 6E (Concise DCF for Node 110): +1F22 6F (Concise DCF for Node 111): +1F22 70 (Concise DCF for Node 112): +1F22 71 (Concise DCF for Node 113): +1F22 72 (Concise DCF for Node 114): +1F22 73 (Concise DCF for Node 115): +1F22 74 (Concise DCF for Node 116): +1F22 75 (Concise DCF for Node 117): +1F22 76 (Concise DCF for Node 118): +1F22 77 (Concise DCF for Node 119): +1F22 78 (Concise DCF for Node 120): +1F22 79 (Concise DCF for Node 121): +1F22 7A (Concise DCF for Node 122): +1F22 7B (Concise DCF for Node 123): +1F22 7C (Concise DCF for Node 124): +1F22 7D (Concise DCF for Node 125): +1F22 7E (Concise DCF for Node 126): +1F22 7F (Concise DCF for Node 127): +2240 (beremiz__IB0_1_64): +2340 (beremiz__IW0_1_64): +2440 (beremiz__ID0_1_64): +4340 (beremiz__QW0_1_64): +********POINTERS********* +{(4096, 0): '__ID0_1_4096_0', + (8768, 1): '__IB0_1_64_24576_1', + (8768, 2): '__IB0_1_64_24578_1', + (9024, 1): '__IW0_1_64_25601_2', + (9024, 2): '__IW0_1_64_25601_3', + (9280, 1): '__ID0_1_64_25638_2', + (9280, 2): '__ID0_1_64_25638_3', + (9280, 3): '__ID0_1_64_25638_4', + (9280, 4): '__ID0_1_64_25638_1', + (17216, 1): '__QW0_1_64_25617_1'} --- a/confnodes/.cvsignore Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
--- a/confnodes/__init__.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-from os import listdir, path
- ('canfestival', _('CANopen support'), _('Map located variables over CANopen'), 'confnodes.canfestival.canfestival.RootClass'),
- ('c_ext', _('C extention'), _('Extend project with C code accessing located variables'), 'confnodes.c_ext.c_ext.RootClass'),
- ('python', _('Python extention'), _('Extend project with Pyhon code executed asynchronously'), 'confnodes.python.python.RootClass')]
-# ('ethercat_master', _('Ethercat master'), _('Map located variables over EtherCat, as a master'), 'ethercat.EthercatPlug')]
--- a/confnodes/c_ext/.cvsignore Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
--- a/confnodes/c_ext/CFileEditor.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,967 +0,0 @@
-from controls import CustomGrid, CustomTable, EditorPanel
-if wx.Platform == '__WXMSW__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- 'other': 'Comic Sans MS',
- faces = { 'times': 'Times',
- 'other': 'new century schoolbook',
-def AppendMenu(parent, help, id, kind, text):
- if wx.VERSION >= (2, 6, 0):
- parent.Append(help=help, id=id, kind=kind, text=text)
- parent.Append(helpString=help, id=id, kind=kind, item=text)
-] = [wx.NewId() for _init_ctrls in range(1)]
-CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class",
- "const", "const_cast", "continue", "default", "delete", "do", "double",
- "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
- "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
- "namespace", "new", "operator", "private", "protected", "public", "register",
- "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
- "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
- "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
- "void", "volatile", "wchar_t", "while"]
-def GetCursorPos(old, new):
- common_length = min(old_length, new_length)
- for i in xrange(common_length):
- if old_length < new_length:
- if common_length > 0 and old[i] != new[i]:
- return i + new_length - old_length
- return i + new_length - old_length + 1
- elif old_length > new_length or i < min(old_length, new_length) - 1:
- if common_length > 0 and old[i] != new[i]:
-class CppEditor(stc.StyledTextCtrl):
- def __init__(self, parent, name, window, controler):
- stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition,
- self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
- self.SetMarginWidth(1, 25)
- self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
- self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
- self.SetLexer(stc.STC_LEX_CPP)
- self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
- self.SetProperty("fold", "1")
- self.SetProperty("tab.timmy.whinge.level", "1")
- self.SetViewWhiteSpace(False)
- #self.SetBufferedDraw(False)
- #self.SetEOLMode(stc.STC_EOL_CRLF)
- #self.SetUseAntiAliasing(True)
- self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
- # Setup a margin to hold fold markers
- #self.SetFoldFlags(16) ### WHAT IS THIS VALUE? WHAT ARE THE OTHER FLAGS? DOES IT MATTER?
- self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
- self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
- self.SetMarginSensitive(2, True)
- self.SetMarginWidth(2, 12)
- if self.fold_symbols == 0:
- # Arrow pointing right for contracted folders, arrow pointing down for expanded
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
- elif self.fold_symbols == 1:
- # Plus for contracted folders, minus for expanded
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
- elif self.fold_symbols == 2:
- # Like a flattened tree control using circular headers and curved joins
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
- elif self.fold_symbols == 3:
- # Like a flattened tree control using square headers
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
- self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
- self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
- self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
- # Make some styles, The lexer defines what each style is used for, we
- # just have to define what each style looks like. This set is adapted from
- # Scintilla sample property files.
- # Global default styles for all languages
- self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
- self.StyleClearAll() # Reset all to be like the default
- # Global default styles for all languages
- self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
- self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
- self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
- self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
- self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
- self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
- self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
- self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
- self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
- self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
- self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
- # register some images for use in the AutoComplete box.
- #self.RegisterImage(1, images.getSmilesBitmap())
- wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
- wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
- wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
- self.Controler = controler
- self.ParentWindow = window
- self.DisableEvents = True
- self.CurrentAction = None
- self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
- self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
- self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
- self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
- def OnModification(self, event):
- if not self.DisableEvents:
- mod_type = event.GetModificationType()
- if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
- if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
- if self.CurrentAction == None:
- elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
- self.Controler.EndBuffering()
- self.CurrentAction = ("Add", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
- if self.CurrentAction == None:
- elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
- self.Controler.EndBuffering()
- self.CurrentAction = ("Delete", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- def OnDoDrop(self, event):
- wx.CallAfter(self.RefreshModel)
- # Buffer the last model state
- def RefreshBuffer(self):
- self.Controler.BufferCFile()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
- def StartBuffering(self):
- self.Controler.StartBuffering()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
- if self.CurrentAction != None:
- self.Controler.EndBuffering()
- self.CurrentAction = None
- self.DisableEvents = True
- old_cursor_pos = self.GetCurrentPos()
- old_text = self.GetText()
- new_text = self.Controler.GetPartText(self.Name)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.GotoPos(new_cursor_pos)
- self.GotoPos(old_cursor_pos)
- self.DisableEvents = False
- def DoGetBestSize(self):
- return self.ParentWindow.GetPanelBestSize()
- def RefreshModel(self):
- self.Controler.SetPartText(self.Name, self.GetText())
- def OnKeyPressed(self, event):
- if self.CallTipActive():
- key = event.GetKeyCode()
- if key == 32 and event.ControlDown():
- pos = self.GetCurrentPos()
-## self.CallTipSetBackground("yellow")
-## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
-## 'show some suff, maybe parameters..\n\n'
-## 'fubar(param1, param2)')
- self.AutoCompSetIgnoreCase(False) # so this needs to match
- # Images are specified with a appended "?type"
- self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
- def OnKillFocus(self, event):
- def OnUpdateUI(self, evt):
- # check for matching braces
- caretPos = self.GetCurrentPos()
- charBefore = self.GetCharAt(caretPos - 1)
- styleBefore = self.GetStyleAt(caretPos - 1)
- if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos - 1
- charAfter = self.GetCharAt(caretPos)
- styleAfter = self.GetStyleAt(caretPos)
- if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos
- braceOpposite = self.BraceMatch(braceAtCaret)
- if braceAtCaret != -1 and braceOpposite == -1:
- self.BraceBadLight(braceAtCaret)
- self.BraceHighlight(braceAtCaret, braceOpposite)
- #pt = self.PointFromPosition(braceOpposite)
- #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
- def OnMarginClick(self, evt):
- # fold and unfold as needed
- if evt.GetMargin() == 2:
- if evt.GetShift() and evt.GetControl():
- lineClicked = self.LineFromPosition(evt.GetPosition())
- if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
- self.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 1)
- if self.GetFoldExpanded(lineClicked):
- self.SetFoldExpanded(lineClicked, False)
- self.Expand(lineClicked, False, True, 0)
- self.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 100)
- self.ToggleFold(lineClicked)
- lineCount = self.GetLineCount()
- # find out if we are folding or unfolding
- for lineNum in range(lineCount):
- if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
- expanding = not self.GetFoldExpanded(lineNum)
- while lineNum < lineCount:
- level = self.GetFoldLevel(lineNum)
- if level & stc.STC_FOLDLEVELHEADERFLAG and \
- (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
- self.SetFoldExpanded(lineNum, True)
- lineNum = self.Expand(lineNum, True)
- lastChild = self.GetLastChild(lineNum, -1)
- self.SetFoldExpanded(lineNum, False)
- if lastChild > lineNum:
- self.HideLines(lineNum+1, lastChild)
- def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
- lastChild = self.GetLastChild(line, level)
- while line <= lastChild:
- self.ShowLines(line, line)
- self.HideLines(line, line)
- self.ShowLines(line, line)
- level = self.GetFoldLevel(line)
- if level & stc.STC_FOLDLEVELHEADERFLAG:
- self.SetFoldExpanded(line, True)
- self.SetFoldExpanded(line, False)
- line = self.Expand(line, doExpand, force, visLevels-1)
- if doExpand and self.GetFoldExpanded(line):
- line = self.Expand(line, True, force, visLevels-1)
- line = self.Expand(line, False, force, visLevels-1)
- self.DisableEvents = True
- self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
- self.DisableEvents = False
- self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
- self.DisableEvents = True
- self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
- self.DisableEvents = False
-#-------------------------------------------------------------------------------
-# Helper for VariablesGrid values
-#-------------------------------------------------------------------------------
-class VariablesTable(CustomTable):
- def GetValue(self, row, col):
- if row < self.GetNumberRows():
- return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
- def _updateColAttrs(self, grid):
- wxGrid -> update the column attributes to add the
- appropriate renderer given the column name.
- Otherwise default to the default renderer.
- for row in range(self.GetNumberRows()):
- for col in range(self.GetNumberCols()):
- colname = self.GetColLabelValue(col, False)
- editor = wx.grid.GridCellTextEditor()
- elif colname == "Class":
- editor = wx.grid.GridCellChoiceEditor()
- editor.SetParameters("input,memory,output")
- elif colname == "Type":
- grid.SetReadOnly(row, col, True)
- grid.SetCellEditor(row, col, editor)
- grid.SetCellRenderer(row, col, renderer)
- grid.SetCellBackgroundColour(row, col, wx.WHITE)
- self.ResizeRow(grid, row)
-[ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID,
- ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON,
- ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON
-] = [wx.NewId() for _init_ctrls in range(6)]
-class VariablesEditor(wx.Panel):
- if wx.VERSION < (2, 6, 0):
- def Bind(self, event, function, id = None):
- event(self, id, function)
- def _init_coll_MainSizer_Growables(self, parent):
- parent.AddGrowableCol(0)
- parent.AddGrowableRow(0)
- def _init_coll_MainSizer_Items(self, parent):
- parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
- parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW)
- def _init_coll_ButtonsSizer_Growables(self, parent):
- parent.AddGrowableCol(0)
- parent.AddGrowableRow(0)
- def _init_coll_ButtonsSizer_Items(self, parent):
- parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT)
- parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0)
- parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0)
- parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0)
- def _init_sizers(self):
- self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
- self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
- self._init_coll_MainSizer_Growables(self.MainSizer)
- self._init_coll_MainSizer_Items(self.MainSizer)
- self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer)
- self._init_coll_ButtonsSizer_Items(self.ButtonsSizer)
- self.SetSizer(self.MainSizer)
- def _init_ctrls(self, prnt):
- wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt,
- size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
- self.VariablesGrid = CustomGrid(id=ID_VARIABLESEDITORVARIABLESGRID,
- name='VariablesGrid', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(-1, -1), style=wx.VSCROLL)
- if wx.VERSION >= (2, 5, 0):
- self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
- self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
- self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
- wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
- wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
- wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
- self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable',
- name='AddVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(122, 32), style=0)
- self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable',
- name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(122, 32), style=0)
- self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^',
- name='UpVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(32, 32), style=0)
- self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v',
- name='DownVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(32, 32), style=0)
- def __init__(self, parent, window, controler):
- self._init_ctrls(parent)
- self.ParentWindow = window
- self.Controler = controler
- self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
- self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
- self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
- self.ColSizes = [40, 200, 150, 150]
- self.VariablesGrid.SetTable(self.Table)
- self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
- "Delete": self.DeleteVariableButton,
- "Up": self.UpVariableButton,
- "Down": self.DownVariableButton})
- def _AddVariable(new_row):
- self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy())
- setattr(self.VariablesGrid, "_AddRow", _AddVariable)
- def _DeleteVariable(row):
- self.Table.RemoveRow(row)
- setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
- def _MoveVariable(row, move):
- new_row = self.Table.MoveRow(row, move)
- setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
- self.VariablesGrid.SetRowLabelSize(0)
- for col in range(self.Table.GetNumberCols()):
- attr = wx.grid.GridCellAttr()
- attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
- self.VariablesGrid.SetColAttr(col, attr)
- self.VariablesGrid.SetColSize(col, self.ColSizes[col])
- self.Table.ResetView(self.VariablesGrid)
- def RefreshModel(self):
- self.Controler.SetVariables(self.Table.GetData())
- # Buffer the last model state
- def RefreshBuffer(self):
- self.Controler.BufferCFile()
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
- self.Table.SetData(self.Controler.GetVariables())
- self.Table.ResetView(self.VariablesGrid)
- self.VariablesGrid.RefreshButtons()
- def DoGetBestSize(self):
- return self.ParentWindow.GetPanelBestSize()
- def OnVariablesGridCellChange(self, event):
- wx.CallAfter(self.RefreshView)
- def OnVariablesGridEditorShown(self, event):
- row, col = event.GetRow(), event.GetCol()
- if self.Table.GetColLabelValue(col) == "Type":
- type_menu = wx.Menu(title='')
- base_menu = wx.Menu(title='')
- for base_type in self.Controler.GetBaseTypes():
- AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
- self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
- type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
- datatype_menu = wx.Menu(title='')
- for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
- AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
- self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
- type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
- rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
- self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
- def GetVariableTypeFunction(self, base_type):
- def VariableTypeFunction(event):
- row = self.VariablesGrid.GetGridCursorRow()
- self.Table.SetValueByName(row, "Type", base_type)
- self.Table.ResetView(self.VariablesGrid)
- return VariableTypeFunction
- def OnVariablesGridCellLeftClick(self, event):
- if event.GetCol() == 0:
- if self.Table.GetValueByName(row, "Class") == "input":
- if self.Table.GetValueByName(i, "Class") == "input":
- elif self.Table.GetValueByName(row, "Class") == "memory":
- if self.Table.GetValueByName(i, "Class") == "memory":
- if self.Table.GetValueByName(i, "Class") == "output":
- data_type = self.Table.GetValueByName(row, "Type")
- var_name = self.Table.GetValueByName(row, "Name")
- base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation()))
- location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num)
- data = wx.TextDataObject(str((location, "location", data_type, var_name, "")))
- dragSource = wx.DropSource(self.VariablesGrid)
- dragSource.SetData(data)
- dragSource.DoDragDrop()
-#-------------------------------------------------------------------------------
-# SVGUIEditor Main Frame Class
-#-------------------------------------------------------------------------------
- ("Includes", CppEditor),
- ("Variables", VariablesEditor),
- ("Globals", CppEditor),
- ("CleanUp", CppEditor),
- ("Retrieve", CppEditor),
- ("Publish", CppEditor),
-#----------------------------------------------------------------------
-# different icons for the collapsed/expanded states.
-# Taken from standard Windows XP collapsed/expanded states.
-#----------------------------------------------------------------------
-def GetCollapsedIconData():
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\
-\xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\
-\xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\
-H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\
-\xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\
-\xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\
-\x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\
-\xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\
-zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\
-\x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\
-~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\
-\x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\
-\xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\
-\xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\
-0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\
-\x00\x00\x00IEND\xaeB`\x82'
-def GetCollapsedIconBitmap():
- return wx.BitmapFromImage(GetCollapsedIconImage())
-def GetCollapsedIconImage():
- stream = cStringIO.StringIO(GetCollapsedIconData())
- return wx.ImageFromStream(stream)
-#----------------------------------------------------------------------
-def GetExpandedIconData():
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\
-\xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\
-\x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\
-\xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\
-\x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\
-\x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\
-\x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\
-\xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\
-\x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\
-\x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\
-\xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\
-\xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\
-\x05\x10\x81\xce\xc9\xa8\xf6><G\xd8\xed\xbbA)X\xd9\x0c\x01\x9a\xc6Q\x14\xd9h\
-[\x04\xda\xd6c\xadFkE\xf0\xc2\xab\xd7\xb7\xc9\x08\x00\xf8\xf6\xbd\x1b\x8cQ\
-\xd8|\xb9\x0f\xd3\x9a\x8a\xc7\x08\x00\x9f?\xdd%\xde\x07\xda\x93\xc3{\x19C\
-\x8a\x9c\x03\x0b8\x17\xe8\x9d\xbf\x02.>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\
-\xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\
-def GetExpandedIconBitmap():
- return wx.BitmapFromImage(GetExpandedIconImage())
-def GetExpandedIconImage():
- stream = cStringIO.StringIO(GetExpandedIconData())
- return wx.ImageFromStream(stream)
-class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton):
- def GetBackgroundBrush(self, dc):
- colBg = self.GetBackgroundColour()
- brush = wx.Brush(colBg, wx.SOLID)
- if self.style & wx.BORDER_NONE:
- myAttr = self.GetDefaultAttributes()
- parAttr = self.GetParent().GetDefaultAttributes()
- myDef = colBg == myAttr.colBg
- parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
- if wx.Platform == "__WXMAC__":
- brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
- elif wx.Platform == "__WXMSW__":
- if self.DoEraseBackground(dc):
- elif myDef and not parDef:
- colBg = self.GetParent().GetBackgroundColour()
- brush = wx.Brush(colBg, wx.SOLID)
- def DrawLabel(self, dc, width, height, dx=0, dy=0):
- if bmp is not None: # if the bitmap is used
- if self.bmpDisabled and not self.IsEnabled():
- if self.bmpFocus and self.hasFocus:
- if self.bmpSelected and not self.up:
- bw,bh = bmp.GetWidth(), bmp.GetHeight()
- hasMask = bmp.GetMask() is not None
- bw = bh = 0 # no bitmap -> size is zero
- dc.SetFont(self.GetFont())
- dc.SetTextForeground(self.GetForegroundColour())
- dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
- label = self.GetLabel()
- tw, th = dc.GetTextExtent(label) # size of text
- dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available
- dc.DrawText(label, 2, (height-th)/2) # draw the text
- dc.SetPen(wx.Pen(self.GetForegroundColour()))
- dc.SetBrush(wx.TRANSPARENT_BRUSH)
- dc.DrawRectangle(0, 0, width, height)
-[ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER,
- ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED,
-] = [wx.NewId() for _init_ctrls in range(4)]
-class CFileEditor(EditorPanel):
- def _init_Editor(self, prnt):
- self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0),
- size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
- self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2 * len(CFILE_PARTS) + 1, vgap=0)
- self.MainSizer.AddGrowableCol(0)
- for idx, (name, panel_class) in enumerate(CFILE_PARTS):
- button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name,
- label=name, bitmap=GetCollapsedIconBitmap(), parent=self.Editor, pos=wx.Point(0, 0),
- size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT)
- button.SetBitmapSelected(GetExpandedIconBitmap())
- button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id)
- self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW)
- if panel_class == VariablesEditor:
- panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler)
- panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
- self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
- self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1}
- self.Spacer = wx.Panel(self.Editor, -1)
- self.SpacerExpanded = True
- self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
- self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
- self.Editor.SetSizer(self.MainSizer)
- def __init__(self, parent, controler, window):
- EditorPanel.__init__(self, parent, "", window, controler)
- img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
- self.Controler.OnCloseEditor(self)
- fullname = self.Controler.CTNFullName()
- if not self.Controler.CFileIsSaved():
- return "~%s~" % fullname
- def GetBufferState(self):
- return self.Controler.GetBufferState()
- self.Controler.LoadPrevious()
- self.Controler.LoadNext()
- for infos in self.Panels.itervalues():
- infos["panel"].RefreshView()
- def GenPanelButtonCallback(self, name):
- def PanelButtonCallback(event):
- return PanelButtonCallback
- def ExpandPanel(self, name):
- infos = self.Panels.get(name, None)
- if infos is not None and not infos["expanded"]:
- infos["expanded"] = True
- infos["button"].SetToggle(True)
- self.MainSizer.AddGrowableRow(infos["row"])
- self.RefreshSizerLayout()
- def CollapsePanel(self, name):
- infos = self.Panels.get(name, None)
- if infos is not None and infos["expanded"]:
- infos["expanded"] = False
- infos["button"].SetToggle(False)
- self.MainSizer.RemoveGrowableRow(infos["row"])
- self.RefreshSizerLayout()
- def TogglePanel(self, name):
- infos = self.Panels.get(name, None)
- infos["expanded"] = not infos["expanded"]
- infos["button"].SetToggle(infos["expanded"])
- self.MainSizer.AddGrowableRow(infos["row"])
- self.MainSizer.RemoveGrowableRow(infos["row"])
- self.RefreshSizerLayout()
- def RefreshSizerLayout(self):
- for infos in self.Panels.itervalues():
- expand_spacer = expand_spacer and not infos["expanded"]
- if self.SpacerExpanded != expand_spacer:
- self.SpacerExpanded = expand_spacer
- self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
- self.MainSizer.RemoveGrowableRow(2 * len(CFILE_PARTS))
- self.MainSizer.Layout()
--- a/confnodes/c_ext/README Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
\ No newline at end of file
--- a/confnodes/c_ext/__init__.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
--- a/confnodes/c_ext/c_ext.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-from xml.dom import minidom
-from ConfigTree import ConfigTreeNode, opjimg
-from CFileEditor import CFileEditor
-from PLCControler import PLCControler, UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
-CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd"))
-TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
- "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
- "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
- XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <xsd:element name="CExtension">
- <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
- <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/>
- EditorType = CFileEditor
- filepath = self.CFileName()
- self.CFile = CFileClasses["CFile"]()
- if os.path.isfile(filepath):
- xmlfile = open(filepath, 'r')
- tree = minidom.parse(xmlfile)
- for child in tree.childNodes:
- if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
- self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
- self.CreateCFileBuffer(True)
- self.CreateCFileBuffer(False)
- return os.path.join(self.CTNPath(), "cfile.xml")
- def GetBaseTypes(self):
- return self.GetCTRoot().GetBaseTypes()
- def GetDataTypes(self, basetypes = False, only_locatables = False):
- return self.GetCTRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
- def GetSizeOfType(self, type):
- return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)
- def SetVariables(self, variables):
- self.CFile.variables.setvariable([])
- variable = CFileClasses["variables_variable"]()
- variable.setname(var["Name"])
- variable.settype(var["Type"])
- variable.setclass(var["Class"])
- self.CFile.variables.appendvariable(variable)
- def GetVariables(self):
- for var in self.CFile.variables.getvariable():
- datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
- def GetVariableLocationTree(self):
- '''See ConfigTreeNode.GetVariableLocationTree() for a description.'''
- current_location = ".".join(map(str, self.GetCurrentLocation()))
- input = memory = output = 0
- for var in self.CFile.variables.getvariable():
- var_size = self.GetSizeOfType(var.gettype())
- if var.getclass() == "input":
- var_class = LOCATION_VAR_INPUT
- if var_size is not None:
- var_location = "%%I%s%s.%d"%(var_size, current_location, input)
- elif var.getclass() == "memory":
- var_class = LOCATION_VAR_INPUT
- if var_size is not None:
- var_location = "%%M%s%s.%d"%(var_size, current_location, memory)
- var_class = LOCATION_VAR_OUTPUT
- if var_size is not None:
- var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
- vars.append({"name": var.getname(),
- "IEC_type": var.gettype(),
- "var_name": var.getname(),
- "location": var_location,
- return {"name": self.BaseParams.getName(),
- "type": LOCATION_CONFNODE,
- "location": self.GetFullIEC_Channel(),
- def SetPartText(self, name, text):
- self.CFile.includes.settext(text)
- elif name == "Globals":
- self.CFile.globals.settext(text)
- self.CFile.initFunction.settext(text)
- elif name == "CleanUp":
- self.CFile.cleanUpFunction.settext(text)
- elif name == "Retrieve":
- self.CFile.retrieveFunction.settext(text)
- elif name == "Publish":
- self.CFile.publishFunction.settext(text)
- def GetPartText(self, name):
- return self.CFile.includes.gettext()
- elif name == "Globals":
- return self.CFile.globals.gettext()
- return self.CFile.initFunction.gettext()
- elif name == "CleanUp":
- return self.CFile.cleanUpFunction.gettext()
- elif name == "Retrieve":
- return self.CFile.retrieveFunction.gettext()
- elif name == "Publish":
- return self.CFile.publishFunction.gettext()
- {"bitmap" : os.path.join("images", "EditCfile"),
- "name" : _("Edit C File"),
- "tooltip" : _("Edit C File"),
- "method" : "_OpenView"},
- def CTNTestModified(self):
- return self.ChangesToSave or not self.CFileIsSaved()
- filepath = self.CFileName()
- text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
- extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
- "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
- "xsi:schemaLocation" : "cext_xsd.xsd"}
- text += self.CFile.generateXMLText("CFile", 0, extras)
- xmlfile = open(filepath,"w")
- xmlfile.write(text.encode("utf-8"))
- self.MarkCFileAsSaved()
- def CTNGenerate_C(self, buildpath, locations):
- @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(str, current_location))
- text = "/* Code generated by Beremiz c_ext confnode */\n\n"
- text += "/* User includes */\n"
- text += self.CFile.includes.gettext()
- text += """/* Beremiz c_ext confnode includes */
- #include "iec_std_lib.h"
- inputs = memories = outputs = 0
- for variable in self.CFile.variables.variable:
- var = {"Name" : variable.getname(), "Type" : variable.gettype()}
- if variable.getclass() == "input":
- var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs)
- elif variable.getclass() == "memory":
- var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
- var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
- text += "/* Beremiz c_ext confnode user variables definition */\n"
- base_types = self.GetCTRoot().GetBaseTypes()
- if var["Type"] in base_types:
- text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
- text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
- text += "/* User variables reference */\n"
- text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
- # Adding user global variables and routines
- text += "/* User internal user variables and routines */\n"
- text += self.CFile.globals.gettext()
- # Adding Beremiz confnode functions
- text += "/* Beremiz confnode functions */\n"
- text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
- text += self.CFile.initFunction.gettext()
- text += "void __cleanup_%s(void)\n{\n"%location_str
- text += self.CFile.cleanUpFunction.gettext()
- text += "void __retrieve_%s(void)\n{\n"%location_str
- text += self.CFile.retrieveFunction.gettext()
- text += "void __publish_%s(void)\n{\n"%location_str
- text += self.CFile.publishFunction.gettext()
- Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
- cfile = open(Gen_Cfile_path,'w')
- matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
- return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
-#-------------------------------------------------------------------------------
-# Current Buffering Management Functions
-#-------------------------------------------------------------------------------
- Return a copy of the cfile model
- return cPickle.loads(cPickle.dumps(model))
- def CreateCFileBuffer(self, saved):
- self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
- self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
- def StartBuffering(self):
- def EndBuffering(self):
- self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
- def MarkCFileAsSaved(self):
- self.CFileBuffer.CurrentSaved()
- def CFileIsSaved(self):
- return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
- def LoadPrevious(self):
- self.CFile = cPickle.loads(self.CFileBuffer.Previous())
- self.CFile = cPickle.loads(self.CFileBuffer.Next())
- def GetBufferState(self):
- first = self.CFileBuffer.IsFirst() and not self.Buffering
- last = self.CFileBuffer.IsLast()
- return not first, not last
- CTNChildrenTypes = [("C_File",_Cfile, "C file")]
- def CTNGenerate_C(self, buildpath, locations):
--- a/confnodes/c_ext/cext_xsd.xsd Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<xsd:schema targetNamespace="cext_xsd.xsd"
- xmlns:cext="cext_xsd.xsd"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified">
- <xsd:element name="CFile">
- <xsd:element name="includes" type="cext:CCode"/>
- <xsd:element name="variables">
- <xsd:element name="variable" minOccurs="0" maxOccurs="unbounded">
- <xsd:attribute name="name" type="xsd:string" use="required"/>
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- <xsd:attribute name="class" use="required">
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="input"/>
- <xsd:enumeration value="memory"/>
- <xsd:enumeration value="output"/>
- <xsd:element name="globals" type="cext:CCode"/>
- <xsd:element name="initFunction" type="cext:CCode"/>
- <xsd:element name="cleanUpFunction" type="cext:CCode"/>
- <xsd:element name="retrieveFunction" type="cext:CCode"/>
- <xsd:element name="publishFunction" type="cext:CCode"/>
- <xsd:complexType name="CCode">
- <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
- <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
--- a/confnodes/canfestival/.cvsignore Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
--- a/confnodes/canfestival/NetworkEditor.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-from subindextable import EditingPanel
-from networkedit import NetworkEditorTemplate
-from controls import EditorPanel
-] = [wx.NewId() for _init_ctrls in range(1)]
-[ID_NETWORKEDITORCONFNODEMENUADDSLAVE, ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE,
- ID_NETWORKEDITORCONFNODEMENUMASTER,
-] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(3)]
-[ID_NETWORKEDITORMASTERMENUNODEINFOS, ID_NETWORKEDITORMASTERMENUDS301PROFILE,
- ID_NETWORKEDITORMASTERMENUDS302PROFILE, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE,
- ID_NETWORKEDITORMASTERMENUADD,
-] = [wx.NewId() for _init_coll_MasterMenu_Items in range(5)]
-[ID_NETWORKEDITORADDMENUSDOSERVER, ID_NETWORKEDITORADDMENUSDOCLIENT,
- ID_NETWORKEDITORADDMENUPDOTRANSMIT, ID_NETWORKEDITORADDMENUPDORECEIVE,
- ID_NETWORKEDITORADDMENUMAPVARIABLE, ID_NETWORKEDITORADDMENUUSERTYPE,
-] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
-class NetworkEditor(EditorPanel, NetworkEditorTemplate):
- def _init_coll_MainSizer_Items(self, parent):
- parent.AddWindow(self.NetworkNodes, 0, border=5, flag=wx.GROW|wx.ALL)
- def _init_coll_MainSizer_Growables(self, parent):
- parent.AddGrowableCol(0)
- parent.AddGrowableRow(0)
- def _init_sizers(self):
- self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0)
- self._init_coll_MainSizer_Items(self.MainSizer)
- self._init_coll_MainSizer_Growables(self.MainSizer)
- self.Editor.SetSizer(self.MainSizer)
- def _init_Editor(self, prnt):
- self.Editor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0),
- size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
- NetworkEditorTemplate._init_ctrls(self, self.Editor)
- def __init__(self, parent, controler, window):
- EditorPanel.__init__(self, parent, "", window, controler)
- NetworkEditorTemplate.__init__(self, controler, window, False)
- img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
- self.RefreshNetworkNodes()
- self.RefreshBufferState()
- self.Controler.OnCloseEditor(self)
- def GetConfNodeMenuItems(self):
- add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_NETWORKEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
- (wx.ITEM_NORMAL, (_('SDO Client'), ID_NETWORKEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
- (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_NETWORKEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
- (wx.ITEM_NORMAL, (_('PDO Receive'), ID_NETWORKEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
- (wx.ITEM_NORMAL, (_('Map Variable'), ID_NETWORKEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
- (wx.ITEM_NORMAL, (_('User Type'), ID_NETWORKEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
- profile = self.Manager.GetCurrentProfileName()
- if profile not in ("None", "DS-301"):
- other_profile_text = _("%s Profile") % profile
- add_menu.append((wx.ITEM_SEPARATOR, None))
- for text, indexes in self.Manager.GetCurrentSpecificMenu():
- add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
- other_profile_text = _('Other Profile')
- master_menu = [(wx.ITEM_NORMAL, (_('Node infos'), ID_NETWORKEDITORMASTERMENUNODEINFOS, '', self.OnNodeInfosMenu)),
- (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_NETWORKEDITORMASTERMENUDS301PROFILE, '', self.OnCommunicationMenu)),
- (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_NETWORKEDITORMASTERMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
- (wx.ITEM_NORMAL, (other_profile_text, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
- (wx.ITEM_SEPARATOR, None),
- (add_menu, (_('Add'), ID_NETWORKEDITORMASTERMENUADD))]
- return [(wx.ITEM_NORMAL, (_('Add slave'), ID_NETWORKEDITORCONFNODEMENUADDSLAVE, '', self.OnAddSlaveMenu)),
- (wx.ITEM_NORMAL, (_('Remove slave'), ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, '', self.OnRemoveSlaveMenu)),
- (wx.ITEM_SEPARATOR, None),
- (master_menu, (_('Master'), ID_NETWORKEDITORCONFNODEMENUMASTER))]
- def RefreshMainMenu(self):
- def RefreshConfNodeMenu(self, confnode_menu):
- confnode_menu.Enable(ID_NETWORKEDITORCONFNODEMENUMASTER, self.NetworkNodes.GetSelection() == 0)
- fullname = self.Controler.CTNFullName()
- if not self.Manager.CurrentIsSaved():
- return "~%s~" % fullname
- self.RefreshCurrentIndexList()
- def RefreshBufferState(self):
- NetworkEditorTemplate.RefreshBufferState(self)
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
- def OnNodeSelectedChanged(self, event):
- NetworkEditorTemplate.OnNodeSelectedChanged(self, event)
- wx.CallAfter(self.ParentWindow.RefreshConfNodeMenu)
--- a/confnodes/canfestival/README Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
\ No newline at end of file
--- a/confnodes/canfestival/SlaveEditor.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-from subindextable import EditingPanel
-from nodeeditor import NodeEditorTemplate
-from controls import EditorPanel
-[ID_SLAVEEDITORCONFNODEMENUNODEINFOS, ID_SLAVEEDITORCONFNODEMENUDS301PROFILE,
- ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE,
- ID_SLAVEEDITORCONFNODEMENUADD,
-] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(5)]
-[ID_SLAVEEDITORADDMENUSDOSERVER, ID_SLAVEEDITORADDMENUSDOCLIENT,
- ID_SLAVEEDITORADDMENUPDOTRANSMIT, ID_SLAVEEDITORADDMENUPDORECEIVE,
- ID_SLAVEEDITORADDMENUMAPVARIABLE, ID_SLAVEEDITORADDMENUUSERTYPE,
-] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
-class SlaveEditor(EditorPanel, NodeEditorTemplate):
- def _init_Editor(self, prnt):
- self.Editor = EditingPanel(prnt, self, self.Controler, self.Editable)
- def __init__(self, parent, controler, window, editable=True):
- self.Editable = editable
- EditorPanel.__init__(self, parent, "", window, controler)
- NodeEditorTemplate.__init__(self, controler, window, False)
- img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
- self.Controler.OnCloseEditor(self)
- def GetConfNodeMenuItems(self):
- add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_SLAVEEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
- (wx.ITEM_NORMAL, (_('SDO Client'), ID_SLAVEEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
- (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_SLAVEEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
- (wx.ITEM_NORMAL, (_('PDO Receive'), ID_SLAVEEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
- (wx.ITEM_NORMAL, (_('Map Variable'), ID_SLAVEEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
- (wx.ITEM_NORMAL, (_('User Type'), ID_SLAVEEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
- profile = self.Controler.GetCurrentProfileName()
- if profile not in ("None", "DS-301"):
- other_profile_text = _("%s Profile") % profile
- add_menu.append((wx.ITEM_SEPARATOR, None))
- for text, indexes in self.Manager.GetCurrentSpecificMenu():
- add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
- other_profile_text = _('Other Profile')
- return [(wx.ITEM_NORMAL, (_('Node infos'), ID_SLAVEEDITORCONFNODEMENUNODEINFOS, '', self.OnNodeInfosMenu)),
- (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_SLAVEEDITORCONFNODEMENUDS301PROFILE, '', self.OnCommunicationMenu)),
- (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
- (wx.ITEM_NORMAL, (other_profile_text, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
- (wx.ITEM_SEPARATOR, None),
- (add_menu, (_('Add'), ID_SLAVEEDITORCONFNODEMENUADD))]
- def RefreshConfNodeMenu(self, confnode_menu):
- confnode_menu.Enable(ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, False)
- fullname = self.Controler.CTNFullName()
- if not self.Controler.CurrentIsSaved():
- return "~%s~" % fullname
- self.Editor.RefreshIndexList()
- def RefreshCurrentIndexList(self):
- def RefreshBufferState(self):
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
--- a/confnodes/canfestival/__init__.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from canfestival import *
--- a/confnodes/canfestival/canfestival.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
-from nodelist import NodeList
-from nodemanager import NodeManager
-import config_utils, gen_cfile, eds_utils
-from networkedit import networkedit
-from objdictedit import objdictedit
-import canfestival_config as local_canfestival_config
-from ConfigTree import ConfigTreeNode
-from commondialogs import CreateNodeDialog
-from SlaveEditor import SlaveEditor
-from NetworkEditor import NetworkEditor
-from gnosis.xml.pickle import *
-from gnosis.xml.pickle.util import setParanoia
-if wx.Platform == '__WXMSW__':
- "CAN_Driver": "can_tcp_win32",
- "CAN_Device": "127.0.0.1",
- "CAN_Baudrate": "125K",
- "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so",
- "CAN_Baudrate": "125K",
-#--------------------------------------------------
-#--------------------------------------------------
-class _SlaveCTN(NodeManager):
- XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <xsd:element name="CanFestivalSlaveNode">
- <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/>
- <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
- <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Slave_NodeId)d"/>
- <xsd:attribute name="Sync_Align" type="xsd:integer" use="optional" default="0"/>
- <xsd:attribute name="Sync_Align_Ratio" use="optional" default="50">
- <xsd:restriction base="xsd:integer">
- <xsd:minInclusive value="1"/>
- <xsd:maxInclusive value="99"/>
- EditorType = SlaveEditor
- # TODO change netname when name change
- NodeManager.__init__(self)
- odfilepath = self.GetSlaveODPath()
- if(os.path.isfile(odfilepath)):
- self.OpenFileInCurrent(odfilepath)
- dialog = CreateNodeDialog(None, wx.OK)
- dialog.Type.Enable(False)
- dialog.GenSYNC.Enable(False)
- if dialog.ShowModal() == wx.ID_OK:
- name, id, nodetype, description = dialog.GetValues()
- profile, filepath = dialog.GetProfile()
- NMT = dialog.GetNMTManagement()
- options = dialog.GetOptions()
- self.CreateNewNode(name, # Name - will be changed at build time
- id, # NodeID - will be changed at build time
- description,# description
- filepath, # prfile filepath
- self.CreateNewNode("SlaveNode", # Name - will be changed at build time
- 0x00, # NodeID - will be changed at build time
- def GetSlaveODPath(self):
- return os.path.join(self.CTNPath(), 'slave.od')
- def GetCanDevice(self):
- return self.CanFestivalSlaveNode.getCan_Device()
- ConfigTreeNode._OpenView(self)
- if self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
- {"bitmap" : os.path.join("images", "NetworkEdit"),
- "tooltip" : "Edit CanOpen slave with ObjdictEdit",
- "method" : "_OpenView"},
- def CTNTestModified(self):
- return self.ChangesToSave or self.OneFileHasChanged()
- return self.SaveCurrentInFile(self.GetSlaveODPath())
- def SetParamsAttribute(self, path, value):
- result = ConfigTreeNode.SetParamsAttribute(self, path, value)
- # Filter IEC_Channel and Name, that have specific behavior
- if path == "BaseParams.IEC_Channel" and self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
- def CTNGenerate_C(self, buildpath, locations):
- @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
- prefix = "_".join(map(str, current_location))
- Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
- # Create a new copy of the model
- slave = self.GetCurrentNodeCopy()
- slave.SetNodeName("OD_%s"%prefix)
- # allow access to local OD from Slave PLC
- pointers = config_utils.LocalODPointers(locations, current_location, slave)
- res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
- res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
- return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
- def LoadPrevious(self):
- self.LoadCurrentPrevious()
- def GetBufferState(self):
- return self.GetCurrentBufferState()
-#--------------------------------------------------
-#--------------------------------------------------
-class MiniNodeManager(NodeManager):
- def __init__(self, parent, filepath, fullname):
- NodeManager.__init__(self)
- self.OpenFileInCurrent(filepath)
- self.Fullname = fullname
- def OnCloseEditor(self, view):
- self.Parent.OnCloseEditor(view)
- def GetBufferState(self):
- return self.GetCurrentBufferState()
-class _NodeListCTN(NodeList):
- XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <xsd:element name="CanFestivalNode">
- <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/>
- <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
- <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Master_NodeId)d"/>
- <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
- EditorType = NetworkEditor
- manager = NodeManager()
- NodeList.__init__(self, manager)
- self.LoadProject(self.CTNPath())
- self.SetNetworkName(self.BaseParams.getName())
- def GetCanDevice(self):
- return self.CanFestivalNode.getCan_Device()
- def SetParamsAttribute(self, path, value):
- result = ConfigTreeNode.SetParamsAttribute(self, path, value)
- # Filter IEC_Channel and Name, that have specific behavior
- if path == "BaseParams.IEC_Channel" and self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
- elif path == "BaseParams.Name":
- self.SetNetworkName(value)
- ConfigTreeNode._OpenView(self)
- if self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
- def _ShowMasterGenerated(self):
- if self._GeneratedView is None:
- buildpath = self._getBuildPath()
- # Eventually create build dir
- if not os.path.exists(buildpath):
- self.GetCTRoot().logger.write_error(_("Error: No PLC built\n"))
- masterpath = os.path.join(buildpath, "MasterGenerated.od")
- if not os.path.exists(masterpath):
- self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
- app_frame = self.GetCTRoot().AppFrame
- manager = MiniNodeManager(self, masterpath, self.CTNFullName() + ".generated_master")
- self._GeneratedView = SlaveEditor(app_frame.TabsOpened, manager, app_frame, False)
- app_frame.EditProjectElement(self._GeneratedView, "MasterGenerated")
- def _CloseGenerateView(self):
- if self._GeneratedView is not None:
- app_frame = self.GetCTRoot().AppFrame
- if app_frame is not None:
- app_frame.DeletePage(self._GeneratedView)
- {"bitmap" : os.path.join("images", "NetworkEdit"),
- "name" : _("Edit network"),
- "tooltip" : _("Edit CanOpen Network with NetworkEdit"),
- "method" : "_OpenView"},
- {"bitmap" : os.path.join("images", "ShowMaster"),
- "name" : _("Show Master"),
- "tooltip" : _("Show Master generated by config_utils"),
- "method" : "_ShowMasterGenerated"}
- def OnCloseEditor(self, view):
- ConfigTreeNode.OnCloseEditor(self, view)
- if self._GeneratedView == view:
- self._GeneratedView = None
- ConfigTreeNode.OnCTNClose(self)
- self._CloseGenerateView()
- def CTNTestModified(self):
- return self.ChangesToSave or self.HasChanged()
- self.SetRoot(self.CTNPath())
- return self.SaveProject() is None
- def CTNGenerate_C(self, buildpath, locations):
- @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
- self._CloseGenerateView()
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- prefix = "_".join(map(str, current_location))
- Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
- # Create a new copy of the model with DCF loaded with PDO mappings for desired location
- master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
- except config_utils.PDOmappingException, e:
- raise Exception, e.message
- res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
- file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
- return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
- def LoadPrevious(self):
- self.Manager.LoadCurrentPrevious()
- self.Manager.LoadCurrentNext()
- def GetBufferState(self):
- return self.Manager.GetCurrentBufferState()
- XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <xsd:element name="CanFestivalInstance">
- <xsd:attribute name="CAN_Driver" type="xsd:string" use="optional" default="%(CAN_Driver)s"/>
- <xsd:attribute name="Debug_mode" type="xsd:boolean" use="optional" default="false"/>
- CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"),
- ("CanOpenSlave",_SlaveCTN, "CanOpen Slave")]
- def GetParamsAttributes(self, path = None):
- infos = ConfigTreeNode.GetParamsAttributes(self, path = None)
- if element["name"] == "CanFestivalInstance":
- for child in element["children"]:
- if child["name"] == "CAN_Driver":
- DLL_LIST= getattr(local_canfestival_config,"DLL_LIST",None)
- if DLL_LIST is not None:
- child["type"] = DLL_LIST
- def GetCanDriver(self):
- can_driver = self.CanFestivalInstance.getCAN_Driver()
- if sys.platform == 'win32':
- if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(can_driver + '_DEBUG.dll'))):
- can_driver += '_DEBUG.dll'
- def CTNGenerate_C(self, buildpath, locations):
- format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
- "candriver" : self.GetCanDriver(),
- "nodes_send_sync" : "",
- "nodes_proceed_sync" : "",
- "slavebootup_register" : "",
- "post_sync_register" : "",
- for child in self.IECSortedChildren():
- childlocstr = "_".join(map(str,child.GetCurrentLocation()))
- nodename = "OD_%s" % childlocstr
- # Try to get Slave Node
- child_data = getattr(child, "CanFestivalSlaveNode", None)
- # Not a slave -> master
- child_data = getattr(child, "CanFestivalNode")
- format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n '%(
- child_data.getNodeId())
- if child_data.getSync_TPDOs():
- format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename)
- format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename)
- # initialize and declare node boot status variables for post_SlaveBootup lookup
- SlaveIDs = child.GetSlaveIDs()
- # define post_SlaveBootup lookup functions
- format_dict["slavebootups"] += (
- "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
- format_dict["slavebootups"] += (
- "int %s_slave_%d_booted = 0;\n"%(nodename, id))
- # define post_SlaveBootup lookup functions
- format_dict["slavebootups"] += (
- "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n"%(nodename)+
- # one case per declared node, mark node as booted
- format_dict["slavebootups"] += (
- " %s_slave_%d_booted = 1;\n"%(nodename, id)+
- format_dict["slavebootups"] += (
- # expression to test if all declared nodes booted
- format_dict["slavebootups"] += " && ".join(["%s_slave_%d_booted"%(nodename, id) for id in SlaveIDs])
- format_dict["slavebootups"] += " )\n" + (
- " Master_post_SlaveBootup(d,nodeId);\n"+
- # register previously declared func as post_SlaveBootup callback for that node
- format_dict["slavebootup_register"] += (
- "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n"%(nodename,nodename))
- align = child_data.getSync_Align()
- align_ratio=child_data.getSync_Align_Ratio()
- format_dict["post_sync"] += (
- "static int %s_CalCount = 0;\n"%(nodename)+
- "static void %s_post_sync(CO_Data* d){\n"%(nodename)+
- " if(%s_CalCount < %d){\n"%(nodename, align)+
- " %s_CalCount++;\n"%(nodename)+
- " align_tick(%d);\n"%(align_ratio)+
- format_dict["post_sync_register"] += (
- "%s_Data.post_sync = %s_post_sync;\n"%(nodename,nodename))
- format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n '%(
- child_data.getNodeId())
- # Include generated OD headers
- format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
- # Declare CAN channels according user filled config
- format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
- child_data.getCAN_Baudrate())
- format_dict["nodes_open"] += 'NODE_OPEN(%s)\n '%(nodename)
- format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n '%(nodename)
- format_dict["nodes_stop"] += 'NODE_STOP(%s)\n '%(nodename)
- filename = os.path.join(os.path.split(__file__)[0],"cf_runtime.c")
- cf_main = open(filename).read() % format_dict
- cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict)
- f = open(cf_main_path,'w')
- return [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True
--- a/confnodes/canfestival/cf_runtime.c Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-#include "canfestival.h"
-/* CanFestival nodes generated OD headers*/
-#define BOARD_DECL(nodename, busname, baudrate)\
- s_BOARD nodename##Board = {busname, baudrate};
-/* CAN channels declaration */
-/* Keep track of init level to cleanup correctly */
-static int init_level=0;
-/* Retrieve PLC cycle time */
-extern int common_ticktime__;
-/* Called once all NetworkEdit declares slaves have booted*/
-static void Master_post_SlaveBootup(CO_Data* d, UNS8 nodeId)
- /* Put the master in operational mode */
- setState(d, Operational);
- /* Ask slave node to go in operational mode */
- masterSendNMTstateChange (d, 0, NMT_Start_Node);
-/* Per master node slavebootup callbacks. Checks that
- * every node have booted before calling Master_post_SlaveBootup */
-/* One slave node post_sync callback.
- * Used to align PLC tick-time on CANopen SYNC
-#define NODE_FORCE_SYNC(nodename) \
- /* Artificially force sync state to 1 so that it is not started */\
- nodename##_Data.CurrentCommunicationState.csSYNC = -1;\
- /* Force sync period to common_ticktime__ so that other node can read it*/\
- *nodename##_Data.COB_ID_Sync = 0x40000080;\
- *nodename##_Data.Sync_Cycle_Period = common_ticktime__ * 1000;
-#define NODE_INIT(nodename, nodeid) \
- /* Defining the node Id */\
- setNodeId(&nodename##_Data, nodeid);\
- setState(&nodename##_Data, Initialisation);
-#define NODE_MASTER_INIT(nodename, nodeid) \
- NODE_FORCE_SYNC(nodename) \
- NODE_INIT(nodename, nodeid)
-#define NODE_SLAVE_INIT(nodename, nodeid) \
- NODE_INIT(nodename, nodeid)
-void InitNodes(CO_Data* d, UNS32 id)
- %(slavebootup_register)s
-#define NODE_STOP(nodename) \
- masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\
- setState(&nodename##_Data, Stopped);\
-void Exit(CO_Data* d, UNS32 id)
-#define NODE_CLOSE(nodename) \
- if(init_level_c-- > 0)\
- canClose(&nodename##_Data);\
-void __cleanup_%(locstr)s(void)
- int init_level_c = init_level;
-#define NODE_OPEN(nodename)\
- if(!canOpen(&nodename##Board,&nodename##_Data)){\
- fprintf(stderr,"Cannot open CAN intefrace %%s at speed %%s\n for CANopen node \"" #nodename "\"",nodename##Board.busname, nodename##Board.baudrate);\
-/*************************** INIT *****************************************/
-int __init_%(locstr)s(int argc,char **argv)
-#ifndef NOT_USE_DYNAMIC_LOADING
- if( !LoadCanDriver("%(candriver)s") ){
- fprintf(stderr, "Cannot load CAN interface library for CanFestival (%(candriver)s)\n");\
- StartTimerLoop(&InitNodes);
-#define NODE_SEND_SYNC(nodename)\
- sendSYNCMessage(&nodename##_Data);
-void __retrieve_%(locstr)s(void)
- /* Locks the stack, so that no changes occurs while PLC access variables
- * TODO : implement buffers to avoid such a big lock
-#define NODE_PROCEED_SYNC(nodename)\
- proceedSYNC(&nodename##_Data);
-void __publish_%(locstr)s(void)
- /* Process sync event */
--- a/confnodes/canfestival/config_utils.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,737 +0,0 @@
-#This file is part of Beremiz, a Integrated Development Environment for
-#programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
-#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
-#See COPYING file for copyrights details.
-#This library is free software; you can redistribute it and/or
-#modify it under the terms of the GNU General Public
-#License as published by the Free Software Foundation; either
-#version 2.1 of the License, or (at your option) any later version.
-#This library is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-#General Public License for more details.
-#You should have received a copy of the GNU General Public
-#License along with this library; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-# Translation between IEC types and Can Open types
-IECToCOType = {"BOOL":0x01, "SINT":0x02, "INT":0x03,"DINT":0x04,"LINT":0x10,
- "USINT":0x05,"UINT":0x06,"UDINT":0x07,"ULINT":0x1B,"REAL":0x08,
- "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07,
- "LWORD":0x1B,"WSTRING":0x0B}
-# Constants for PDO types
-SlavePDOType = {"I" : TPDO, "Q" : RPDO}
-InvertPDOType = {RPDO : TPDO, TPDO : RPDO}
-PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800}
-PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180}
-VariableIncrement = 0x100
-VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000}
-VariableDirText = {TPDO : "__I", RPDO : "__Q"}
-VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6)))
-TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
-#-------------------------------------------------------------------------------
-# Specific exception for PDO mapping errors
-#-------------------------------------------------------------------------------
-class PDOmappingException(Exception):
-def LE_to_BE(value, size):
- Convert Little Endian to Big Endian
- @param value: value expressed in integer
- @param size: number of bytes generated
- @return: a string containing the value converted
- data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
- list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
- return "".join([chr(int(car, 16)) for car in list_car])
-def GetNodePDOIndexes(node, type, parameters = False):
- Find the PDO indexes of a node
- @param type: type of PDO searched (RPDO or TPDO or both)
- @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
- @return: a list of indexes found
- indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
- indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF])
- return [idx + 0x200 for idx in indexes]
-def SearchNodePDOMapping(loc_infos, node):
- Find the PDO indexes of a node
- @param type: type of PDO searched (RPDO or TPDO or both)
- @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
- @return: a list of indexes found
- model = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8)
- for PDOidx in GetNodePDOIndexes(node, loc_infos["pdotype"]):
- values = node.GetEntry(PDOidx)
- for subindex, mapping in enumerate(values):
- if subindex != 0 and mapping & 0xFFFFFF00 == model:
- return PDOidx, subindex
-def GeneratePDOMappingDCF(idx, cobid, transmittype, pdomapping):
- Build concise DCF value for configuring a PDO
- @param idx: index of PDO parameters
- @param cobid: PDO generated COB ID
- @param transmittype : PDO transmit type
- @param pdomapping: list of PDO mappings
- @return: a tuple of value and number of parameters to add to DCF
- # Create entry for RPDO or TPDO parameters and Disable PDO
- dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x80000000 + cobid, 4)
- # Set Transmit type synchrone
- dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1)
- # ---- INDEX ----- --- SUBINDEX ---- ----- SIZE ------ ------ DATA ------
- dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4)
- if len(pdomapping) > 0:
- dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(0x00, 1) + LE_to_BE(0x01, 4) + LE_to_BE(len(pdomapping), 1)
- for subindex, (name, loc_infos) in enumerate(pdomapping):
- value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"]
- dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4)
- return dcfdata, nbparams
-class ConciseDCFGenerator:
- def __init__(self, nodelist, nodename):
- # Dictionary of location informations classed by name
- # Dictionary of location that have not been mapped yet
- self.LocationsNotMapped = {}
- # Dictionary of location informations classed by name
- self.MasterMapping = {}
- # List of COB IDs available
- self.ListCobIDAvailable = range(0x180, 0x580)
- # Dictionary of mapping value where unexpected variables are stored
- self.TrashVariables = {}
- # Dictionary of pointed variables
- self.PointedVariables = {}
- self.NodeList = nodelist
- self.Manager = self.NodeList.Manager
- self.MasterNode = self.Manager.GetCurrentNodeCopy()
- self.MasterNode.SetNodeName(nodename)
- self.PrepareMasterNode()
- def GetPointedVariables(self):
- return self.PointedVariables
- def RemoveUsedNodeCobId(self, node):
- Remove all PDO COB ID used by the given node from the list of available COB ID
- @return: a tuple of number of RPDO and TPDO for the node
- # Get list of all node TPDO and RPDO indexes
- nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True)
- nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True)
- # Mark all the COB ID of the node already mapped PDO as not available
- for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes:
- pdo_cobid = node.GetEntry(PdoIdx, 0x01)
- # Extract COB ID, if PDO isn't active
- pdo_cobid -= 0x80000000
- # Remove COB ID from the list of available COB ID
- if pdo_cobid in self.ListCobIDAvailable:
- self.ListCobIDAvailable.remove(pdo_cobid)
- return len(nodeRpdoIndexes), len(nodeTpdoIndexes)
- def PrepareMasterNode(self):
- Add mandatory entries for DCF generation into MasterNode.
- # Adding DCF entry into Master node
- if not self.MasterNode.IsEntry(0x1F22):
- self.MasterNode.AddEntry(0x1F22, 1, "")
- self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode)
- # Adding trash mappable variables for unused mapped datas
- idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID()
- # Add an entry for storing unexpected all variable
- self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode)
- for subidx, (size, typeidx) in enumerate(TrashVariables):
- # Add a subentry for storing unexpected variable of this size
- self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode)
- self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode)
- # Store the mapping value for this entry
- self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size
- RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode)
- # Store the indexes of the first RPDO and TPDO available for MasterNode
- self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber}
- # Prepare MasterNode with all nodelist slaves
- for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()):
- node = nodeinfos["Node"]
- RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
- # Get Slave's default SDO server parameters
- RSDO_cobid = node.GetEntry(0x1200,0x01)
- RSDO_cobid = 0x600 + nodeid
- TSDO_cobid = node.GetEntry(0x1200,0x02)
- TSDO_cobid = 0x580 + nodeid
- # Configure Master's SDO parameters entries
- self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode)
- self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid)
- self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid)
- self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid)
- def GetMasterNode(self):
- def AddParamsToDCF(self, nodeid, data, nbparams):
- Add entry to DCF, for the requested nodeID
- @param nodeid: id of the slave (int)
- @param data: data to add to slave DCF (string)
- @param nbparams: number of params added to slave DCF (int)
- # Get current DCF for slave
- nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid)
- # Extract data and number of params in current DCF
- if nodeDCF != None and nodeDCF != '':
- tmpnbparams = [i for i in nodeDCF[:4]]
- nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
- data = nodeDCF[4:] + data
- dcf = LE_to_BE(nbparams, 0x04) + data
- # Set new DCF for slave
- self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
- def GetEmptyPDO(self, nodeid, pdotype, start_index=None):
- Search a not configured PDO for a slave
- @param node: the slave node object
- @param pdotype: type of PDO to generated (RPDO or TPDO)
- @param start_index: Index where search must start (default: None)
- @return tuple of PDO index, COB ID and number of subindex defined
- # If no start_index defined, start with PDOtype base index
- if start_index is None:
- index = PDOTypeBaseIndex[pdotype]
- # Search for all PDO possible index until find a configurable PDO
- # starting from start_index
- while index < PDOTypeBaseIndex[pdotype] + 0x200:
- values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200)
- if values != None and values[0] > 0:
- # Check that all subindex upper than 0 equal 0 => configurable PDO
- if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True):
- cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1)
- # If no COB ID defined in PDO, generate a new one (not used)
- if len(self.ListCobIDAvailable) == 0:
- # Calculate COB ID from standard values
- if index < PDOTypeBaseIndex[pdotype] + 4:
- cobid = PDOTypeBaseCobId[pdotype] + 0x100 * (index - PDOTypeBaseIndex[pdotype]) + nodeid
- if cobid not in self.ListCobIDAvailable:
- cobid = self.ListCobIDAvailable.pop(0)
- return index, cobid, values[0]
- def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs):
- Record a new mapping request for a slave, and add related slave config to the DCF
- @param nodeid: id of the slave (int)
- @param pdotype: type of PDO to generated (RPDO or TPDO)
- @param pdomapping: list od variables to map with PDO
- # Add an entry to MasterMapping
- self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype],
- "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
- # Return the data to add to DCF
- return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
- return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
- def GenerateDCF(self, locations, current_location, sync_TPDOs):
- Generate Concise DCF of MasterNode for the locations list given
- @param locations: list of locations to be mapped
- @param current_location: tuple of the located prefixes not to be considered
- @param sync_TPDOs: indicate if TPDO must be synchronous
- #-------------------------------------------------------------------------------
- # Verify that locations correspond to real slave variables
- #-------------------------------------------------------------------------------
- # Get list of locations check if exists and mappables -> put them in IECLocations
- for location in locations:
- COlocationtype = IECToCOType[location["IEC_TYPE"]]
- name = location["NAME"]
- if name in self.IECLocations:
- if self.IECLocations[name]["type"] != COlocationtype:
- raise PDOmappingException, _("Type conflict for location \"%s\"") % name
- # Get only the part of the location that concern this node
- loc = location["LOC"][len(current_location):]
- # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
- if len(loc) not in (2, 3, 4):
- raise PDOmappingException, _("Bad location size : %s") % str(loc)
- direction = location["DIR"]
- sizelocation = location["SIZE"]
- # Extract and check nodeid
- nodeid, index, subindex = loc[:3]
- # Check Id is in slave node list
- if nodeid not in self.NodeList.SlaveNodes.keys():
- raise PDOmappingException, _("Non existing node ID : %d (variable %s)") % (nodeid,name)
- # Get the model for this node (made from EDS)
- node = self.NodeList.SlaveNodes[nodeid]["Node"]
- # Extract and check index and subindex
- if not node.IsEntry(index, subindex):
- raise PDOmappingException, _("No such index/subindex (%x,%x) in ID : %d (variable %s)") % (index,subindex,nodeid,name)
- subentry_infos = node.GetSubentryInfos(index, subindex)
- if subentry_infos and subentry_infos["pdo"]:
- if sizelocation == "X" and len(loc) > 3:
- elif sizelocation != "X" and len(loc) > 3:
- raise PDOmappingException, _("Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
- if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
- raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
- typeinfos = node.GetEntryInfos(COlocationtype)
- self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
- "nodeid": nodeid, "index": index,"subindex": subindex,
- "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation}
- raise PDOmappingException, _("Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
- #-------------------------------------------------------------------------------
- # Search for locations already mapped
- #-------------------------------------------------------------------------------
- for name, locationinfos in self.IECLocations.items():
- node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"]
- # Search if slave has a PDO mapping this locations
- result = SearchNodePDOMapping(locationinfos, node)
- index, subindex = result
- # Get COB ID of the PDO
- cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1)
- # Add PDO to MasterMapping
- if cobid not in self.MasterMapping.keys():
- # Verify that PDO transmit type is conform to sync_TPDOs
- transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2)
- if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF:
- # Change TransmitType to SYNCHRONE
- data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, [])
- # Change TransmitType to ASYCHRONE
- data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, [])
- # Add entry to slave dcf to change transmit type of
- self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams)
- values = node.GetEntry(index)
- # Store the size of each entry mapped in PDO
- for value in values[1:]:
- mapping.append(value % 0x100)
- self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping}
- # Indicate that this PDO entry must be saved
- if locationinfos["bit"] is not None:
- if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType):
- self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex]
- if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]):
- self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name)
- self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
- # Add location to those that haven't been mapped yet
- if locationinfos["nodeid"] not in self.LocationsNotMapped.keys():
- self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []}
- self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos))
- #-------------------------------------------------------------------------------
- # Build concise DCF for the others locations
- #-------------------------------------------------------------------------------
- for nodeid, locations in self.LocationsNotMapped.items():
- node = self.NodeList.SlaveNodes[nodeid]["Node"]
- # Initialize number of params and data to add to node DCF
- # Generate the best PDO mapping for each type of PDO
- for pdotype in (TPDO, RPDO):
- if len(locations[pdotype]) > 0:
- result = self.GetEmptyPDO(nodeid, pdotype)
- raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
- pdoindex, pdocobid, pdonbparams = result
- for name, loc_infos in locations[pdotype]:
- pdosize += loc_infos["size"]
- # If pdo's size > 64 bits
- if pdosize > 64 or len(pdomapping) >= pdonbparams:
- # Generate a new PDO Mapping
- data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
- nbparams += nbaddedparams
- pdosize = loc_infos["size"]
- pdomapping = [(name, loc_infos)]
- result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
- raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
- pdoindex, pdocobid, pdonbparams = result
- pdomapping.append((name, loc_infos))
- # If there isn't locations yet but there is still a PDO to generate
- if len(pdomapping) > 0:
- # Generate a new PDO Mapping
- data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
- nbparams += nbaddedparams
- # Add number of params and data to node DCF
- self.AddParamsToDCF(nodeid, dataparams, nbparams)
- #-------------------------------------------------------------------------------
- # Master Node Configuration
- #-------------------------------------------------------------------------------
- # Generate Master's Configuration from informations stored in MasterMapping
- for cobid, pdo_infos in self.MasterMapping.items():
- # Get next PDO index in MasterNode for this PDO type
- current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]]
- # Search if there is already a PDO in MasterNode with this cob id
- for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True):
- if self.MasterNode.GetEntry(idx, 1) == cobid:
- # Add a PDO to MasterNode if not PDO have been found
- if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]:
- addinglist = [current_idx, current_idx + 0x200]
- self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode)
- self.MasterNode.SetEntry(current_idx, 0x01, cobid)
- # Increment the number of PDO for this PDO type
- self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1
- # Change the transmit type of the PDO
- self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
- self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
- for item in pdo_infos["mapping"]:
- if isinstance(item, ListType):
- # Add some subentries to PDO mapping if there is not enough
- self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
- # Generate MasterNode's PDO mapping
- for subindex, variable in enumerate(mapping):
- if isinstance(variable, (IntType, LongType)):
- # If variable is an integer then variable is unexpected
- self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
- typeidx, varname = variable
- variable_infos = self.IECLocations[varname]
- # Calculate base index for storing variable
- mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \
- VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
- variable_infos["nodeid"]
- indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
- variable_infos["sizelocation"],
- '_'.join(map(str,current_location)),
- variable_infos["nodeid"])
- # Search for an entry that has an empty subindex
- while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
- if not self.MasterNode.IsEntry(mapvariableidx):
- # Add entry to MasterNode
- self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
- nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
- # Get Number of subentries already defined
- nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
- # if entry is full, go to next entry possible or stop now
- if nbsubentries == 0xFF:
- mapvariableidx += 8 * VariableIncrement
- # Verify that a not full entry has been found
- if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
- # Generate subentry name
- if variable_infos["bit"] != None:
- subindexname = "%(index)d_%(subindex)d_%(bit)d"%variable_infos
- subindexname = "%(index)d_%(subindex)d"%variable_infos
- # If entry have just been created, no subentry have to be added
- self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode)
- # Add informations to the new subentry created
- self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname})
- self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx})
- # Set value of the PDO mapping
- typeinfos = self.Manager.GetEntryInfos(typeidx)
- value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
- self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
- # Add variable to pointed variables
- self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
-def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename):
- Fills a CanFestival network editor model, with DCF with requested PDO mappings.
- @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,...)
- @param nodelist: CanFestival network editor model
- @return: a modified copy of the given CanFestival network editor model
- dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
- dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
- masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
- # allow access to local OD from Master PLC
- pointers.update(LocalODPointers(locations, current_location, masternode))
- return masternode,pointers
-def LocalODPointers(locations, current_location, slave):
- for location in locations:
- COlocationtype = IECToCOType[location["IEC_TYPE"]]
- name = location["NAME"]
- if name in IECLocations:
- if IECLocations[name] != COlocationtype:
- raise PDOmappingException, _("Type conflict for location \"%s\"") % name
- # Get only the part of the location that concern this node
- loc = location["LOC"][len(current_location):]
- # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
- if len(loc) not in (2, 3, 4):
- raise PDOmappingException, _("Bad location size : %s") % str(loc)
- # Extract and check nodeid
- index, subindex = loc[:2]
- # Extract and check index and subindex
- if not slave.IsEntry(index, subindex):
- raise PDOmappingException, _("No such index/subindex (%x,%x) (variable %s)") % (index, subindex, name)
- subentry_infos = slave.GetSubentryInfos(index, subindex)
- if subentry_infos["type"] != COlocationtype:
- raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
- IECLocations[name] = COlocationtype
- pointers[(index, subindex)] = name
-if __name__ == "__main__":
-Usage of config_utils.py test :
- Displays help informations for config_utils
- Reset the reference result of config_utils test.
- Use with caution. Be sure that config_utils
- is currently working properly.
- # Boolean that indicate if reference result must be redefined
- # Extract command options
- opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"])
- except getopt.GetoptError:
- # print help information and exit:
- if o in ("-h", "--help"):
- elif o in ("-r", "--reset"):
- # Extract workspace base folder
- base_folder = sys.path[0]
- base_folder = os.path.split(base_folder)[0]
- # Add CanFestival folder to search pathes
- sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
- from nodemanager import *
- # Open the test nodelist contained into test_config folder
- manager = NodeManager()
- nodelist = NodeList(manager)
- result = nodelist.LoadProject("test_config")
- # List of locations, we try to map for test
- locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)},
- {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)},
- {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)},
- {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)},
- {"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24578_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24578,1)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}]
- # Generate MasterNode configuration
- masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
- except ValueError, message:
- print "%s\nTest Failed!"%message
- # Get Text corresponding to MasterNode
- result_node = masternode.PrintString()
- result_vars = pprint.pformat(pointedvariables)
- result = result_node + "\n********POINTERS*********\n" + result_vars + "\n"
- # If reset has been choosen
- # Write Text into reference result file
- testfile = open("test_config/result.txt", "w")
- print "Reset Successful!"
- testfile = open("test_config/result_tmp.txt", "w")
- os.system("diff test_config/result.txt test_config/result_tmp.txt")
- os.remove("test_config/result_tmp.txt")
--- a/confnodes/canfestival/test_config/eds/PEAK MicroMod.eds Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1289 +0,0 @@
-Description=PEAK MicroMod CANopenIA Generic
-ModificationTime=05:05PM
-ModificationDate=03-23-2005
-FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds
-VendorName=PEAK System Technik
-ProductName=PEAK MicroMod CANopenIA Generic
-ProductNumber=0x00100000
-RevisionNumber=0x00010001
-DynamicChannelsSupported=0
-ParameterName=Device Type
-ParameterName=Error Register
-ParameterName=Identity Object
-ParameterName=number of entries
-ParameterName=Product Code
-ParameterName=Revision number
-ParameterName=PEAK Status Register
-ParameterName=COB-ID SYNC
-ParameterName=Manufacturer Device Name
-ParameterName=Manufacturer Hardware Version
-ParameterName=Manufacturer Software Version
-ParameterName=Guard Time
-ParameterName=Life Time Factor
-ParameterName=Store Parameter Field
-ParameterName=Number of Entries
-ParameterName=Save all Parameters
-ParameterName=Restore Default Parameters
-ParameterName=Number of Entries
-ParameterName=Restore all Default Parameters
-ParameterName=Consumer Heartbeat Time
-ParameterName=Number of Entries
-ParameterName=Consumer Heartbeat Time
-ParameterName=Consumer Heartbeat Time
-ParameterName=Consumer Heartbeat Time
-ParameterName=Producer Heartbeat Time
-ParameterName=Verify Configuration
-ParameterName=Number of entries
-ParameterName=Configuration date
-ParameterName=Configuration time
-ParameterName=Receive PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x200
-ParameterName=Transmission Type
-ParameterName=Receive PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x300
-ParameterName=Transmission Type
-ParameterName=Receive PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x80000400
-ParameterName=Transmission Type
-ParameterName=Receive PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x80000500
-ParameterName=Transmission Type
-ParameterName=Receive PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=PDO Mapping Entry
-ParameterName=Receive PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=Receive PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=Receive PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=Transmit PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x180
-ParameterName=Transmission Type
-ParameterName=Inhibit Time
-ParameterName=Event Timer
-ParameterName=Transmit PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x280
-ParameterName=Transmission Type
-ParameterName=Inhibit Time
-ParameterName=Event Timer
-ParameterName=Transmit PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x380
-ParameterName=Transmission Type
-ParameterName=Inhibit Time
-ParameterName=Event Timer
-ParameterName=Transmit PDO Communication Parameter
-ParameterName=Number of Entries
-DefaultValue=$NODEID+0x80000480
-ParameterName=Transmission Type
-ParameterName=Inhibit Time
-ParameterName=Event Timer
-ParameterName=Transmit PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=PDO Mapping Entry
-ParameterName=Transmit PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=Transmit PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=PDO Mapping Entry
-ParameterName=Transmit PDO Mapping Parameter
-ParameterName=Number of Entries
-ParameterName=Download Program Data
-ParameterName=Number of elements
-ParameterName=Download Program Data - HW Settings
-ParameterName=Read Digital Input 8-bit
-ParameterName=Number of Elements
-ParameterName=DigInput8_1
-ParameterName=Polarity Digital Input
-ParameterName=Number of Elements
-ParameterName=Polarity8_1
-ParameterName=Write Digital Output 8-bit
-ParameterName=Number of elements
-ParameterName=DigOutput8_1
-ParameterName=Polarity Digital Output
-ParameterName=Number of Elements
-ParameterName=Polarity8_1
-ParameterName=Error Mode Digital Output
-ParameterName=Number of elements
-ParameterName=Error Mode 1
-ParameterName=Error Value Digital Output
-ParameterName=Number of elements
-ParameterName=Error Value 1
-ParameterName=Read Analog Input 16-bit
-ParameterName=Number of elements
-ParameterName=AnalogInput16_1
-ParameterName=AnalogInput16_2
-ParameterName=AnalogInput16_3
-ParameterName=AnalogInput16_4
-ParameterName=AnalogInput16_5
-ParameterName=AnalogInput16_6
-ParameterName=AnalogInput16_7
-ParameterName=AnalogInput16_8
-ParameterName=Write Analog Output 16-bit
-ParameterName=Number of elements
-ParameterName=AnalogOutput16_1
-ParameterName=AnalogOutput16_2
-ParameterName=AnalogOutput16_3
-ParameterName=AnalogOutput16_4
-ParameterName=Analog Input Global Interrupt
-ParameterName=Analog Input Interrupt Delta
-ParameterName=NrOfObjects
-ParameterName=Analog Input Delta 1
-ParameterName=Analog Input Delta 2
-ParameterName=Analog Input Delta 3
-ParameterName=Analog Input Delta 4
-ParameterName=Analog Input Delta 5
-ParameterName=Analog Input Delta 6
-ParameterName=Analog Input Delta 7
-ParameterName=Analog Input Delta 8
-ParameterName=Error Mode Analog Output
-ParameterName=Number of elements
-ParameterName=Error Mode 1
-ParameterName=Error Mode 2
-ParameterName=Error Mode 3
-ParameterName=Error Mode 4
-ParameterName=Error Value Analog Output
-ParameterName=Number of elements
-ParameterName=Error Value 1
-ParameterName=Error Value 2
-ParameterName=Error Value 3
-ParameterName=Error Value 4
--- a/confnodes/canfestival/test_config/master.od Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
-<PyObject module="node" class="Node" id="148584620">
-<attr name="Profile" type="dict" id="148589396" >
-<attr name="Description" type="string" value="" />
-<attr name="Dictionary" type="dict" id="148592132" >
- <key type="numeric" value="4096" />
- <val type="numeric" value="302" />
- <key type="numeric" value="4097" />
- <val type="numeric" value="0" />
- <key type="numeric" value="6144" />
- <val type="list" id="148585004" >
- <item type="string" value="{True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4]" />
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <key type="numeric" value="5120" />
- <val type="list" id="148586060" >
- <item type="numeric" value="448" />
- <item type="numeric" value="1" />
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <key type="numeric" value="4101" />
- <val type="numeric" value="1073741952" />
- <key type="numeric" value="4102" />
- <val type="numeric" value="50000" />
- <key type="numeric" value="8192" />
- <val type="numeric" value="0" />
- <key type="numeric" value="6656" />
- <val type="list" id="148585228" >
- <item type="numeric" value="268501000" />
- <key type="numeric" value="5632" />
- <val type="list" id="148585036" >
- <item type="numeric" value="536870920" />
- <key type="numeric" value="4120" />
- <val type="list" id="148585292" >
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <item type="numeric" value="0" />
- <key type="numeric" value="4118" />
- <val type="list" id="148585100" >
- <item type="numeric" value="4195804" />
-<attr name="SpecificMenu" type="list" id="148584044" >
-<attr name="ParamsDictionary" type="dict" id="148592268" >
-<attr name="UserMapping" type="dict" id="148592404" >
- <key type="numeric" value="8192" />
- <val type="dict" id="148592540" >
- <key type="string" value="need" />
- <val type="False" value="" />
- <key type="string" value="values" />
- <val type="list" id="148585868" >
- <item type="dict" id="148592676" >
- <key type="string" value="access" />
- <val type="string" value="rw" />
- <key type="string" value="pdo" />
- <val type="True" value="" />
- <key type="string" value="type" />
- <val type="numeric" value="5" />
- <key type="string" value="name" />
- <val type="string">Read Inputs</val>
- <key type="string" value="name" />
- <val type="string">Read Inputs</val>
- <key type="string" value="struct" />
- <val type="numeric" value="1" />
-<attr name="DS302" type="dict" id="148592812" >
- <key type="numeric" value="7968" />
- <val type="dict" id="148592948" >
- <key type="string" value="need" />
- <val type="False" value="" />
- <key type="string" value="values" />
- <val type="list" id="148584684" >
- <item type="dict" id="148593084" >
- <key type="string" value="access" />
- <val type="string" value="ro" />
- <key type="string" value="pdo" />
- <val type="False" value="" />
- <key type="string" value="type" />
- <val type="numeric" value="5" />
- <key type="string" value="name" />
- <val type="string" value="Number of Entries" />
- <item type="dict" id="148593220" >
- <key type="string" value="access" />
- <val type="string" value="rw" />
- <key type="string" value="pdo" />
- <val type="False" value="" />
- <key type="string" value="type" />
- <val type="numeric" value="15" />
- <key type="string" value="name" />
- <val type="string" value="Store DCF for node %d[(sub)]" />
- <key type="string" value="nbmax" />
- <val type="numeric" value="127" />
- <key type="string" value="name" />
- <val type="string" value="Store DCF" />
- <key type="string" value="struct" />
- <val type="numeric" value="7" />
- <key type="numeric" value="7969" />
- <val type="dict" id="148593356" >
- <key type="string" value="need" />
- <val type="False" value="" />
- <key type="string" value="values" />
- <val type="list" id="148585516" >
- <item type="dict" id="148593492" >
- <key type="string" value="access" />
- <val type="string" value="ro" />
- <key type="string" value="pdo" />
- <val type="False" value="" />
- <key type="string" value="type" />
- <val type="numeric" value="5" />
- <key type="string" value="name" />
- <val type="string" value="Number of Entries" />
- <item type="dict" id="148593628" >
- <key type="string" value="access" />
- <val type="string" value="rw" />
- <key type="string" value="pdo" />
- <val type="False" value="" />
- <key type="string" value="type" />
- <val type="numeric" value="2" />
- <key type="string" value="name" />
- <val type="string" value="Storage Format for Node %d[(sub)]" />
- <key type="string" value="nbmax" />
- <val type="numeric" value="127" />
- <key type="string" value="name" />
- <val type="string" value="Storage Format" />
- <key type="string" value="struct" />
- <val type="numeric" value="7" />
- <key type="numeric" value="7970" />
- <val type="dict" id="148593764" >
- <key type="string" value="need" />
- <val type="False" value="" />
- <key type="string" value="values" />
- <val type="list" id="148594956" >
- <item type="dict" id="148593900" >
- <key type="string" value="access" />
- <val type="string" value="ro" />
- <key type="string" value="pdo" />
- <val type="False" value="" />
- <key type="string" value="type" />
- <val type="numeric" value="5" />
- <key type="string" value="name" />
- <val type="string" value="Number of Entries" />
- <item type="dict" id="148594036" >
- <key type="string" value="access" />
- <val type="string" value="rw" />
- <key type="string" value="pdo" />
- <val type="False" value="" />
- <key type="string" value="type" />
- <val type="numeric" value="15" />
- <key type="string" value="name" />
- <val type="string" value="Concise DCF for Node %d[(sub)]" />
- <key type="string" value="nbmax" />
- <val type="numeric" value="127" />
- <key type="string" value="name" />
- <val type="string" value="Concise DCF" />
- <key type="string" value="struct" />
- <val type="numeric" value="7" />
-<attr name="ProfileName" type="string" value="None" />
-<attr name="Type" type="string">master</attr>
-<attr name="ID" type="numeric" value="0" />
-<attr name="Name" type="string">TestMaster</attr>
--- a/confnodes/canfestival/test_config/nodelist.cpj Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-Node64DCFName=PEAK MicroMod.eds
--- a/confnodes/canfestival/test_config/result.txt Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-1001 (Error Register): 0
-1005 (SYNC COB ID): 40000080
-1006 (Communication / Cycle Period): C350
-1016 (Consumer Heartbeat Time):
-1016 01 (Consumer Heartbeat Time): 4005DC
-1018 02 (Product Code): 0
-1018 03 (Revision Number): 0
-1018 04 (Serial Number): 0
-1280 (Client SDO 1 Parameter):
-1280 01 (COB ID Client to Server (Transmit SDO)): 640
-1280 02 (COB ID Server to Client (Receive SDO)): 5C0
-1280 03 (Node ID of the SDO Server): 40
-1400 (Receive PDO 1 Parameter):
-1400 01 (COB ID used by PDO): 1C0
-1400 02 (Transmission Type): 1
-1400 03 (Inhibit Time): 0
-1400 04 (Compatibility Entry): 0
-1400 05 (Event Timer): 0
-1401 (Receive PDO 2 Parameter):
-1401 01 (COB ID used by PDO): 2C0
-1401 02 (Transmission Type): 1
-1401 03 (Inhibit Time): 0
-1401 04 (Compatibility Entry): 0
-1401 05 (Event Timer): 0
-1402 (Receive PDO 3 Parameter):
-1402 01 (COB ID used by PDO): 182
-1402 02 (Transmission Type): 1
-1402 03 (Inhibit Time): 0
-1402 04 (Compatibility Entry): 0
-1402 05 (Event Timer): 0
-1403 (Receive PDO 4 Parameter):
-1403 01 (COB ID used by PDO): 183
-1403 02 (Transmission Type): 1
-1403 03 (Inhibit Time): 0
-1403 04 (Compatibility Entry): 0
-1403 05 (Event Timer): 0
-1404 (Receive PDO 5 Parameter):
-1404 01 (COB ID used by PDO): 181
-1404 02 (Transmission Type): 1
-1404 03 (Inhibit Time): 0
-1404 04 (Compatibility Entry): 0
-1404 05 (Event Timer): 0
-1600 (Receive PDO 1 Mapping):
-1600 01 (PDO 1 Mapping for an application object 1): 22400108
-1600 02 (PDO 1 Mapping for an application object 2): 0
-1601 (Receive PDO 2 Mapping):
-1601 01 (PDO 2 Mapping for an application object 1): 20000310
-1601 02 (PDO 2 Mapping for an application object 2): 23400110
-1601 03 (PDO 2 Mapping for an application object 3): 23400210
-1601 04 (PDO 2 Mapping for an application object 4): 20000310
-1602 (Receive PDO 3 Mapping):
-1602 01 (PDO 3 Mapping for an application object 1): 24400120
-1602 02 (PDO 3 Mapping for an application object 2): 24400220
-1603 (Receive PDO 4 Mapping):
-1603 01 (PDO 4 Mapping for an application object 1): 24400320
-1604 (Receive PDO 5 Mapping):
-1604 01 (PDO 5 Mapping for an application object 1): 22400208
-1604 02 (PDO 5 Mapping for an application object 2): 24400420
-1800 (Transmit PDO 1 Parameter):
-1800 01 (COB ID used by PDO): {True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4]
-1800 02 (Transmission Type): 0
-1800 03 (Inhibit Time): 0
-1800 04 (Compatibility Entry): 0
-1800 05 (Event Timer): 0
-1801 (Transmit PDO 2 Parameter):
-1801 01 (COB ID used by PDO): 340
-1801 02 (Transmission Type): 1
-1801 03 (Inhibit Time): 0
-1801 04 (Compatibility Entry): 0
-1801 05 (Event Timer): 0
-1A00 (Transmit PDO 1 Mapping):
-1A00 01 (PDO 1 Mapping for a process data variable 1): 10010008
-1A01 (Transmit PDO 2 Mapping):
-1A01 01 (PDO 2 Mapping for a process data variable 1): 43400110
-1A01 02 (PDO 2 Mapping for a process data variable 2): 20000310
-1A01 03 (PDO 2 Mapping for a process data variable 3): 20000310
-1A01 04 (PDO 2 Mapping for a process data variable 4): 20000310
-1F22 01 (Concise DCF for Node 1):
-1F22 02 (Concise DCF for Node 2):
-1F22 03 (Concise DCF for Node 3):
-1F22 04 (Concise DCF for Node 4):
-1F22 05 (Concise DCF for Node 5):
-1F22 06 (Concise DCF for Node 6):
-1F22 07 (Concise DCF for Node 7):
-1F22 08 (Concise DCF for Node 8):
-1F22 09 (Concise DCF for Node 9):
-1F22 0A (Concise DCF for Node 10):
-1F22 0B (Concise DCF for Node 11):
-1F22 0C (Concise DCF for Node 12):
-1F22 0D (Concise DCF for Node 13):
-1F22 0E (Concise DCF for Node 14):
-1F22 0F (Concise DCF for Node 15):
-1F22 10 (Concise DCF for Node 16):
-1F22 11 (Concise DCF for Node 17):
-1F22 12 (Concise DCF for Node 18):
-1F22 13 (Concise DCF for Node 19):
-1F22 14 (Concise DCF for Node 20):
-1F22 15 (Concise DCF for Node 21):
-1F22 16 (Concise DCF for Node 22):
-1F22 17 (Concise DCF for Node 23):
-1F22 18 (Concise DCF for Node 24):
-1F22 19 (Concise DCF for Node 25):
-1F22 1A (Concise DCF for Node 26):
-1F22 1B (Concise DCF for Node 27):
-1F22 1C (Concise DCF for Node 28):
-1F22 1D (Concise DCF for Node 29):
-1F22 1E (Concise DCF for Node 30):
-1F22 1F (Concise DCF for Node 31):
-1F22 20 (Concise DCF for Node 32):
-1F22 21 (Concise DCF for Node 33):
-1F22 22 (Concise DCF for Node 34):
-1F22 23 (Concise DCF for Node 35):
-1F22 24 (Concise DCF for Node 36):
-1F22 25 (Concise DCF for Node 37):
-1F22 26 (Concise DCF for Node 38):
-1F22 27 (Concise DCF for Node 39):
-1F22 28 (Concise DCF for Node 40):
-1F22 29 (Concise DCF for Node 41):
-1F22 2A (Concise DCF for Node 42):
-1F22 2B (Concise DCF for Node 43):
-1F22 2C (Concise DCF for Node 44):
-1F22 2D (Concise DCF for Node 45):
-1F22 2E (Concise DCF for Node 46):
-1F22 2F (Concise DCF for Node 47):
-1F22 30 (Concise DCF for Node 48):
-1F22 31 (Concise DCF for Node 49):
-1F22 32 (Concise DCF for Node 50):
-1F22 33 (Concise DCF for Node 51):
-1F22 34 (Concise DCF for Node 52):
-1F22 35 (Concise DCF for Node 53):
-1F22 36 (Concise DCF for Node 54):
-1F22 37 (Concise DCF for Node 55):
-1F22 38 (Concise DCF for Node 56):
-1F22 39 (Concise DCF for Node 57):
-1F22 3A (Concise DCF for Node 58):
-1F22 3B (Concise DCF for Node 59):
-1F22 3C (Concise DCF for Node 60):
-1F22 3D (Concise DCF for Node 61):
-1F22 3E (Concise DCF for Node 62):
-1F22 3F (Concise DCF for Node 63):
-1F22 40 (Concise DCF for Node 64): 23 arg defined
-1F22 40, arg 1: 1800 01 00000004 800001C0
-1F22 40, arg 2: 1800 02 00000001 01
-1F22 40, arg 3: 1800 01 00000004 000001C0
-1F22 40, arg 4: 1801 01 00000004 800002C0
-1F22 40, arg 5: 1801 02 00000001 01
-1F22 40, arg 6: 1801 01 00000004 000002C0
-1F22 40, arg 7: 1401 01 00000004 80000340
-1F22 40, arg 8: 1401 02 00000001 01
-1F22 40, arg 9: 1401 01 00000004 00000340
-1F22 40, arg 10: 1804 01 00000004 80000181
-1F22 40, arg 11: 1804 02 00000001 01
-1F22 40, arg 12: 1804 01 00000004 00000181
-1F22 40, arg 13: 1A04 01 00000004 60020108
-1F22 40, arg 14: 1A04 02 00000004 64260120
-1F22 40, arg 15: 1805 01 00000004 80000182
-1F22 40, arg 16: 1805 02 00000001 01
-1F22 40, arg 17: 1805 01 00000004 00000182
-1F22 40, arg 18: 1A05 01 00000004 64260220
-1F22 40, arg 19: 1A05 02 00000004 64260320
-1F22 40, arg 20: 1806 01 00000004 80000183
-1F22 40, arg 21: 1806 02 00000001 01
-1F22 40, arg 22: 1806 01 00000004 00000183
-1F22 40, arg 23: 1A06 01 00000004 64260420
-1F22 41 (Concise DCF for Node 65):
-1F22 42 (Concise DCF for Node 66):
-1F22 43 (Concise DCF for Node 67):
-1F22 44 (Concise DCF for Node 68):
-1F22 45 (Concise DCF for Node 69):
-1F22 46 (Concise DCF for Node 70):
-1F22 47 (Concise DCF for Node 71):
-1F22 48 (Concise DCF for Node 72):
-1F22 49 (Concise DCF for Node 73):
-1F22 4A (Concise DCF for Node 74):
-1F22 4B (Concise DCF for Node 75):
-1F22 4C (Concise DCF for Node 76):
-1F22 4D (Concise DCF for Node 77):
-1F22 4E (Concise DCF for Node 78):
-1F22 4F (Concise DCF for Node 79):
-1F22 50 (Concise DCF for Node 80):
-1F22 51 (Concise DCF for Node 81):
-1F22 52 (Concise DCF for Node 82):
-1F22 53 (Concise DCF for Node 83):
-1F22 54 (Concise DCF for Node 84):
-1F22 55 (Concise DCF for Node 85):
-1F22 56 (Concise DCF for Node 86):
-1F22 57 (Concise DCF for Node 87):
-1F22 58 (Concise DCF for Node 88):
-1F22 59 (Concise DCF for Node 89):
-1F22 5A (Concise DCF for Node 90):
-1F22 5B (Concise DCF for Node 91):
-1F22 5C (Concise DCF for Node 92):
-1F22 5D (Concise DCF for Node 93):
-1F22 5E (Concise DCF for Node 94):
-1F22 5F (Concise DCF for Node 95):
-1F22 60 (Concise DCF for Node 96):
-1F22 61 (Concise DCF for Node 97):
-1F22 62 (Concise DCF for Node 98):
-1F22 63 (Concise DCF for Node 99):
-1F22 64 (Concise DCF for Node 100):
-1F22 65 (Concise DCF for Node 101):
-1F22 66 (Concise DCF for Node 102):
-1F22 67 (Concise DCF for Node 103):
-1F22 68 (Concise DCF for Node 104):
-1F22 69 (Concise DCF for Node 105):
-1F22 6A (Concise DCF for Node 106):
-1F22 6B (Concise DCF for Node 107):
-1F22 6C (Concise DCF for Node 108):
-1F22 6D (Concise DCF for Node 109):
-1F22 6E (Concise DCF for Node 110):
-1F22 6F (Concise DCF for Node 111):
-1F22 70 (Concise DCF for Node 112):
-1F22 71 (Concise DCF for Node 113):
-1F22 72 (Concise DCF for Node 114):
-1F22 73 (Concise DCF for Node 115):
-1F22 74 (Concise DCF for Node 116):
-1F22 75 (Concise DCF for Node 117):
-1F22 76 (Concise DCF for Node 118):
-1F22 77 (Concise DCF for Node 119):
-1F22 78 (Concise DCF for Node 120):
-1F22 79 (Concise DCF for Node 121):
-1F22 7A (Concise DCF for Node 122):
-1F22 7B (Concise DCF for Node 123):
-1F22 7C (Concise DCF for Node 124):
-1F22 7D (Concise DCF for Node 125):
-1F22 7E (Concise DCF for Node 126):
-1F22 7F (Concise DCF for Node 127):
-2240 (beremiz__IB0_1_64):
-2340 (beremiz__IW0_1_64):
-2440 (beremiz__ID0_1_64):
-4340 (beremiz__QW0_1_64):
-********POINTERS*********
-{(4096, 0): '__ID0_1_4096_0',
- (8768, 1): '__IB0_1_64_24576_1',
- (8768, 2): '__IB0_1_64_24578_1',
- (9024, 1): '__IW0_1_64_25601_2',
- (9024, 2): '__IW0_1_64_25601_3',
- (9280, 1): '__ID0_1_64_25638_2',
- (9280, 2): '__ID0_1_64_25638_3',
- (9280, 3): '__ID0_1_64_25638_4',
- (9280, 4): '__ID0_1_64_25638_1',
- (17216, 1): '__QW0_1_64_25617_1'}
--- a/confnodes/python/PythonEditor.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,505 +0,0 @@
-from controls import EditorPanel
-if wx.Platform == '__WXMSW__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- 'other': 'Comic Sans MS',
-elif wx.Platform == '__WXMAC__':
- faces = { 'times': 'Times New Roman',
- 'other': 'Comic Sans MS',
- faces = { 'times': 'Times',
- 'other': 'new century schoolbook',
-] = [wx.NewId() for _init_ctrls in range(1)]
-def GetCursorPos(old, new):
- common_length = min(old_length, new_length)
- for i in xrange(common_length):
- if old_length < new_length:
- if common_length > 0 and old[i] != new[i]:
- return i + new_length - old_length
- return i + new_length - old_length + 1
- elif old_length > new_length or i < min(old_length, new_length) - 1:
- if common_length > 0 and old[i] != new[i]:
-class PythonEditor(EditorPanel):
- def _init_Editor(self, prnt):
- self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
- name="TextViewer", pos=wx.DefaultPosition,
- size=wx.DefaultSize, style=0)
- self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
- self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
- self.Editor.SetLexer(stc.STC_LEX_PYTHON)
- self.Editor.SetKeyWords(0, " ".join(keyword.kwlist))
- self.Editor.SetProperty("fold", "1")
- self.Editor.SetProperty("tab.timmy.whinge.level", "1")
- self.Editor.SetMargins(0,0)
- self.Editor.SetViewWhiteSpace(False)
- self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
- self.Editor.SetEdgeColumn(78)
- # Set up the numbers in the margin for margin #1
- self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
- # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
- self.Editor.SetMarginWidth(1, 40)
- # Setup a margin to hold fold markers
- self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
- self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS)
- self.Editor.SetMarginSensitive(2, True)
- self.Editor.SetMarginWidth(2, 12)
- if self.fold_symbols == 0:
- # Arrow pointing right for contracted folders, arrow pointing down for expanded
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
- elif self.fold_symbols == 1:
- # Plus for contracted folders, minus for expanded
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
- elif self.fold_symbols == 2:
- # Like a flattened tree control using circular headers and curved joins
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
- elif self.fold_symbols == 3:
- # Like a flattened tree control using square headers
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
- self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
- self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
- self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
- if wx.Platform == '__WXMSW__':
- self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New')
- elif wx.Platform == '__WXMAC__':
- # TODO: if this looks fine on Linux too, remove the Mac-specific case
- # and use this whenever OS != MSW.
- self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco')
- defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize()
- self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize)
- # Clear styles and revert to default.
- self.Editor.StyleClearAll()
- # Following style specs only indicate differences from default.
- # The rest remains unchanged.
- # Line numbers in margin
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
- self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
- self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
- self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
- self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
- # Strings and characters
- self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
- self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
- self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
- self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
- self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
- self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
- self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
- self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
- # Identifiers. I leave this as not bold because everything seems
- # to be an identifier if it doesn't match the above criterae
- self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
- self.Editor.SetCaretForeground("BLUE")
- self.Editor.SetSelBackground(1, '#66CCFF')
- self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
- self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
- # register some images for use in the AutoComplete box.
- #self.RegisterImage(1, images.getSmilesBitmap())
- self.Editor.RegisterImage(1,
- wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
- self.Editor.RegisterImage(2,
- wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
- self.Editor.RegisterImage(3,
- wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
- # Indentation and tab stuff
- self.Editor.SetIndent(4) # Proscribed indent size for wx
- self.Editor.SetIndentationGuides(True) # Show indent guides
- self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
- self.Editor.SetTabIndents(True) # Tab key indents
- self.Editor.SetTabWidth(4) # Proscribed tab size for wx
- self.Editor.SetUseTabs(False) # Use spaces rather than tabs, or
- # TabTimmy will complain!
- self.Editor.SetViewWhiteSpace(False) # Don't view white space
- # EOL: Since we are loading/saving ourselves, and the
- # strings will always have \n's in them, set the STC to
- self.Editor.SetEOLMode(wx.stc.STC_EOL_LF)
- self.Editor.SetViewEOL(False)
- # No right-edge mode indicator
- self.Editor.SetEdgeMode(stc.STC_EDGE_NONE)
- self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
- self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
- self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
- self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR)
- def __init__(self, parent, controler, window):
- EditorPanel.__init__(self, parent, "", window, controler)
- self.DisableEvents = False
- self.CurrentAction = None
- img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
- self.Controler.OnCloseEditor(self)
- fullname = self.Controler.CTNFullName()
- if not self.Controler.PythonIsSaved():
- return "~%s~" % fullname
- def GetBufferState(self):
- return self.Controler.GetBufferState()
- self.Controler.LoadPrevious()
- self.Controler.LoadNext()
- def OnModification(self, event):
- if not self.DisableEvents:
- mod_type = event.GetModificationType()
- if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
- if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
- if self.CurrentAction is None:
- elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
- self.Controler.EndBuffering()
- self.CurrentAction = ("Add", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
- if self.CurrentAction == None:
- elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
- self.Controler.EndBuffering()
- self.CurrentAction = ("Delete", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- def OnDoDrop(self, event):
- wx.CallAfter(self.RefreshModel)
- # Buffer the last model state
- def RefreshBuffer(self):
- self.Controler.BufferPython()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
- def StartBuffering(self):
- self.Controler.StartBuffering()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
- if self.CurrentAction != None:
- self.Controler.EndBuffering()
- self.CurrentAction = None
- self.DisableEvents = True
- old_cursor_pos = self.Editor.GetCurrentPos()
- old_text = self.Editor.GetText()
- new_text = self.Controler.GetPythonCode()
- self.Editor.SetText(new_text)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.Editor.GotoPos(new_cursor_pos)
- self.Editor.GotoPos(old_cursor_pos)
- self.Editor.ScrollToColumn(0)
- self.Editor.EmptyUndoBuffer()
- self.DisableEvents = False
- self.Editor.Colourise(0, -1)
- def RefreshModel(self):
- self.Controler.SetPythonCode(self.Editor.GetText())
- def OnKeyPressed(self, event):
- if self.Editor.CallTipActive():
- self.Editor.CallTipCancel()
- key = event.GetKeyCode()
- if key == 32 and event.ControlDown():
- pos = self.Editor.GetCurrentPos()
-## self.CallTipSetBackground("yellow")
-## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
-## 'show some suff, maybe parameters..\n\n'
-## 'fubar(param1, param2)')
- self.Editor.AutoCompSetIgnoreCase(False) # so this needs to match
- # Images are specified with a appended "?type"
- self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
- def OnKillFocus(self, event):
- self.Editor.AutoCompCancel()
- def OnUpdateUI(self, evt):
- # check for matching braces
- caretPos = self.Editor.GetCurrentPos()
- charBefore = self.Editor.GetCharAt(caretPos - 1)
- styleBefore = self.Editor.GetStyleAt(caretPos - 1)
- if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos - 1
- charAfter = self.Editor.GetCharAt(caretPos)
- styleAfter = self.Editor.GetStyleAt(caretPos)
- if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos
- braceOpposite = self.Editor.BraceMatch(braceAtCaret)
- if braceAtCaret != -1 and braceOpposite == -1:
- self.Editor.BraceBadLight(braceAtCaret)
- self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
- #pt = self.Editor.PointFromPosition(braceOpposite)
- #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
- #self.Editor.Refresh(False)
- def OnMarginClick(self, evt):
- # fold and unfold as needed
- if evt.GetMargin() == 2:
- if evt.GetShift() and evt.GetControl():
- lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
- if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
- self.Editor.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 1)
- if self.Editor.GetFoldExpanded(lineClicked):
- self.Editor.SetFoldExpanded(lineClicked, False)
- self.Expand(lineClicked, False, True, 0)
- self.Editor.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 100)
- self.Editor.ToggleFold(lineClicked)
- lineCount = self.Editor.GetLineCount()
- # find out if we are folding or unfolding
- for lineNum in range(lineCount):
- if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
- expanding = not self.Editor.GetFoldExpanded(lineNum)
- while lineNum < lineCount:
- level = self.Editor.GetFoldLevel(lineNum)
- if level & stc.STC_FOLDLEVELHEADERFLAG and \
- (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
- self.Editor.SetFoldExpanded(lineNum, True)
- lineNum = self.Expand(lineNum, True)
- lastChild = self.Editor.GetLastChild(lineNum, -1)
- self.Editor.SetFoldExpanded(lineNum, False)
- if lastChild > lineNum:
- self.Editor.HideLines(lineNum+1, lastChild)
- def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
- lastChild = self.Editor.GetLastChild(line, level)
- while line <= lastChild:
- self.Editor.ShowLines(line, line)
- self.Editor.HideLines(line, line)
- self.Editor.ShowLines(line, line)
- level = self.Editor.GetFoldLevel(line)
- if level & stc.STC_FOLDLEVELHEADERFLAG:
- self.Editor.SetFoldExpanded(line, True)
- self.Editor.SetFoldExpanded(line, False)
- line = self.Expand(line, doExpand, force, visLevels-1)
- if doExpand and self.Editor.GetFoldExpanded(line):
- line = self.Expand(line, True, force, visLevels-1)
- line = self.Expand(line, False, force, visLevels-1)
- self.DisableEvents = True
- self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
- self.DisableEvents = False
- self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
- self.DisableEvents = True
- self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
- self.DisableEvents = False
--- a/confnodes/python/README Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Asynchronous Python Interpreter
--- a/confnodes/python/__init__.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
--- a/confnodes/python/modules/__init__.py Tue May 08 16:31:12 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("__")]
- helpfilename = path.join(_base_path, name, "README")
- if path.isfile(helpfilename):
- helps.append(open(helpfilename).readline().strip())
--- a/confnodes/python/modules/svgui/README Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
\ No newline at end of file
--- a/confnodes/python/modules/svgui/__init__.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
--- a/confnodes/python/modules/svgui/livesvg.js Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-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) {
-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]
- gadget.updateValues(json_parse(dataReceived.kwargs));
- //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState);
- function init(self, arg1){
- //console.log("Object received : " + 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);
--- a/confnodes/python/modules/svgui/pous.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1428 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="http://www.plcopen.org/xml/tc6.xsd"
- xmlns:xhtml="http://www.w3.org/1999/xhtml"
- xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
- <fileHeader companyName="Beremiz"
- creationDateTime="2008-12-14T16:53:26"/>
- <contentHeader name="Beremiz non-standard POUs library"
- modificationDateTime="2009-08-12T15:35:33">
- <pou name="GetBoolString" pouType="functionBlock">
- <variable name="VALUE">
- <pou name="TextCtrl" pouType="functionBlock">
- <variable name="back_id">
- <variable name="set_text">
- <variable name="SVGUI_TEXTCTRL">
- <derived name="python_eval"/>
- <variable name="setstate_Command">
- <derived name="python_eval"/>
- <block localId="1" width="193" height="160" typeName="CONCAT">
- <position x="626" y="122"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="43"/>
- <connection refLocalId="2">
- <position x="626" y="165"/>
- <position x="535" y="165"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="89"/>
- <connection refLocalId="3">
- <position x="626" y="211"/>
- <position x="535" y="211"/>
- <variable formalParameter="IN3">
- <relPosition x="0" y="135"/>
- <connection refLocalId="6">
- <position x="626" y="257"/>
- <position x="532" y="257"/>
- <variable formalParameter="OUT">
- <relPosition x="193" y="43"/>
- <inVariable localId="2" height="30" width="460">
- <position x="75" y="150"/>
- <relPosition x="460" y="15"/>
- <expression>'createSVGUIControl("textControl", back_id="'</expression>
- <inVariable localId="3" height="35" width="85">
- <position x="450" y="196"/>
- <relPosition x="85" y="15"/>
- <expression>back_id</expression>
- <inVariable localId="6" height="30" width="50">
- <position x="482" y="242"/>
- <relPosition x="50" y="15"/>
- <expression>'")'</expression>
- <block localId="7" width="125" height="115" typeName="python_eval" instanceName="SVGUI_TEXTCTRL">
- <position x="909" y="75"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="45"/>
- <connection refLocalId="9">
- <position x="909" y="120"/>
- <position x="886" y="120"/>
- <position x="886" y="85"/>
- <position x="869" y="85"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="90"/>
- <connection refLocalId="1" formalParameter="OUT">
- <position x="909" y="165"/>
- <position x="819" y="165"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="45"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="90"/>
- <inVariable localId="9" height="30" width="70">
- <position x="799" y="70"/>
- <relPosition x="70" y="15"/>
- <expression>BOOL#1</expression>
- <outVariable localId="10" height="30" width="30">
- <position x="1094" y="150"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="7" formalParameter="RESULT">
- <position x="1094" y="165"/>
- <position x="1034" y="165"/>
- <expression>ID</expression>
- <connector name="CREATED" localId="11" height="30" width="110">
- <position x="1096" y="105"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="7" formalParameter="ACK">
- <position x="1096" y="120"/>
- <position x="1034" y="120"/>
- <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
- <position x="957" y="472"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="50"/>
- <connection refLocalId="31" formalParameter="OUT">
- <position x="957" y="522"/>
- <position x="909" y="522"/>
- <position x="909" y="444"/>
- <position x="857" y="444"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="110"/>
- <connection refLocalId="12" formalParameter="OUT">
- <position x="957" y="582"/>
- <position x="822" y="582"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="50"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="110"/>
- <continuation name="CREATED" localId="5" height="30" width="110">
- <position x="589" y="429"/>
- <relPosition x="110" y="15"/>
- <block localId="12" width="186" height="288" typeName="CONCAT">
- <position x="636" y="536"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="46"/>
- <connection refLocalId="14">
- <position x="636" y="582"/>
- <position x="526" y="582"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="99"/>
- <connection refLocalId="8">
- <position x="636" y="635"/>
- <position x="526" y="635"/>
- <variable formalParameter="IN3">
- <relPosition x="0" y="152"/>
- <connection refLocalId="15">
- <position x="636" y="688"/>
- <position x="527" y="688"/>
- <variable formalParameter="IN4">
- <relPosition x="0" y="205"/>
- <connection refLocalId="32">
- <position x="636" y="741"/>
- <position x="528" y="741"/>
- <variable formalParameter="IN5">
- <relPosition x="0" y="258"/>
- <connection refLocalId="16">
- <position x="636" y="794"/>
- <position x="528" y="794"/>
- <variable formalParameter="OUT">
- <relPosition x="186" y="46"/>
- <inVariable localId="8" height="30" width="53">
- <position x="473" y="620"/>
- <relPosition x="53" y="15"/>
- <expression>ID</expression>
- <inVariable localId="13" height="35" width="100">
- <position x="599" y="469"/>
- <relPosition x="100" y="17"/>
- <expression>set_text</expression>
- <inVariable localId="14" height="30" width="120">
- <position x="406" y="567"/>
- <relPosition x="120" y="15"/>
- <expression>'setAttr('</expression>
- <inVariable localId="15" height="30" width="122">
- <position x="405" y="673"/>
- <relPosition x="122" y="15"/>
- <expression>',"text","'</expression>
- <inVariable localId="16" height="30" width="50">
- <position x="478" y="779"/>
- <relPosition x="50" y="15"/>
- <expression>'")'</expression>
- <block localId="31" width="75" height="105" typeName="AND">
- <position x="782" y="403"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="41"/>
- <connection refLocalId="5">
- <position x="782" y="444"/>
- <position x="699" y="444"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="83"/>
- <connection refLocalId="13">
- <position x="782" y="486"/>
- <position x="699" y="486"/>
- <variable formalParameter="OUT">
- <relPosition x="75" y="41"/>
- <inVariable localId="32" height="30" width="90">
- <position x="438" y="726"/>
- <relPosition x="90" y="15"/>
- <expression>text</expression>
- <pou name="Button" pouType="functionBlock">
- <variable name="back_id">
- <variable name="sele_id">
- <variable name="toggle">
- <variable name="set_state">
- <variable name="state_in">
- <variable name="state_out">
- <variable name="init_Command">
- <derived name="python_eval"/>
- <variable name="GetButtonState">
- <derived name="GetBoolString"/>
- <variable name="setstate_Command">
- <derived name="python_eval"/>
- <variable name="getstate_Command">
- <derived name="python_poll"/>
- <variable name="GetButtonToggle">
- <derived name="GetBoolString"/>
- <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
- <position x="838" y="32"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="50"/>
- <connection refLocalId="10">
- <position x="838" y="82"/>
- <position x="781" y="82"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="110"/>
- <connection refLocalId="2" formalParameter="OUT">
- <position x="838" y="142"/>
- <position x="641" y="142"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="50"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="110"/>
- <block localId="2" width="150" height="442" typeName="CONCAT">
- <position x="491" y="92"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="50"/>
- <connection refLocalId="3">
- <position x="491" y="142"/>
- <position x="433" y="142"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="110"/>
- <connection refLocalId="11">
- <position x="491" y="202"/>
- <position x="431" y="202"/>
- <variable formalParameter="IN3">
- <relPosition x="0" y="170"/>
- <connection refLocalId="5">
- <position x="491" y="262"/>
- <position x="431" y="262"/>
- <variable formalParameter="IN4">
- <relPosition x="0" y="230"/>
- <connection refLocalId="12">
- <position x="491" y="322"/>
- <position x="430" y="322"/>
- <variable formalParameter="IN5">
- <relPosition x="0" y="290"/>
- <connection refLocalId="23">
- <position x="491" y="382"/>
- <position x="463" y="382"/>
- <position x="463" y="370"/>
- <position x="430" y="370"/>
- <variable formalParameter="IN6">
- <relPosition x="0" y="350"/>
- <connection refLocalId="24" formalParameter="CODE">
- <position x="491" y="442"/>
- <position x="429" y="442"/>
- <variable formalParameter="IN7">
- <relPosition x="0" y="410"/>
- <connection refLocalId="9">
- <position x="491" y="502"/>
- <position x="430" y="502"/>
- <variable formalParameter="OUT">
- <relPosition x="150" y="50"/>
- <inVariable localId="3" height="30" width="400">
- <position x="33" y="127"/>
- <relPosition x="400" y="15"/>
- <expression>'createSVGUIControl("button",back_id="'</expression>
- <inVariable localId="5" height="30" width="140">
- <position x="291" y="247"/>
- <relPosition x="140" y="15"/>
- <expression>'",sele_id="'</expression>
- <inVariable localId="9" height="30" width="180">
- <position x="250" y="487"/>
- <relPosition x="180" y="15"/>
- <expression>',active=True)'</expression>
- <inVariable localId="10" height="30" width="70">
- <position x="711" y="67"/>
- <relPosition x="70" y="15"/>
- <expression>BOOL#1</expression>
- <inVariable localId="11" height="35" width="85">
- <position x="346" y="187"/>
- <relPosition x="85" y="15"/>
- <expression>back_id</expression>
- <inVariable localId="12" height="35" width="85">
- <position x="345" y="307"/>
- <relPosition x="85" y="15"/>
- <expression>sele_id</expression>
- <inVariable localId="13" height="35" width="100">
- <position x="452" y="639"/>
- <relPosition x="100" y="15"/>
- <expression>set_state</expression>
- <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonState">
- <position x="239" y="897"/>
- <variable formalParameter="VALUE">
- <relPosition x="0" y="30"/>
- <connection refLocalId="32">
- <position x="239" y="927"/>
- <position x="181" y="927"/>
- <variable formalParameter="CODE">
- <relPosition x="140" y="30"/>
- <outVariable localId="29" height="30" width="53">
- <position x="1015" y="127"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="1" formalParameter="RESULT">
- <position x="1015" y="142"/>
- <position x="963" y="142"/>
- <expression>ID</expression>
- <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
- <position x="810" y="640"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="50"/>
- <connection refLocalId="31" formalParameter="OUT">
- <position x="810" y="690"/>
- <position x="762" y="690"/>
- <position x="762" y="612"/>
- <position x="710" y="612"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="110"/>
- <connection refLocalId="7" formalParameter="OUT">
- <position x="810" y="750"/>
- <position x="643" y="750"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="50"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="110"/>
- <connector name="CREATED" localId="30" height="30" width="110">
- <position x="1014" y="67"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="1" formalParameter="ACK">
- <position x="1014" y="82"/>
- <position x="963" y="82"/>
- <continuation name="CREATED" localId="6" height="30" width="110">
- <position x="442" y="597"/>
- <relPosition x="110" y="15"/>
- <block localId="31" width="75" height="105" typeName="AND">
- <position x="635" y="571"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="41"/>
- <connection refLocalId="6">
- <position x="635" y="612"/>
- <position x="552" y="612"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="83"/>
- <connection refLocalId="13">
- <position x="635" y="654"/>
- <position x="552" y="654"/>
- <variable formalParameter="OUT">
- <relPosition x="75" y="41"/>
- <inVariable localId="32" height="30" width="90">
- <position x="91" y="912"/>
- <relPosition x="90" y="15"/>
- <expression>state_in</expression>
- <outVariable localId="33" height="30" width="100">
- <position x="1334" y="1184"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="26" formalParameter="OUT">
- <position x="1334" y="1199"/>
- <position x="1286" y="1199"/>
- <expression>state_out</expression>
- <block localId="7" width="150" height="319" typeName="CONCAT">
- <position x="493" y="701"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="49"/>
- <connection refLocalId="14">
- <position x="493" y="750"/>
- <position x="379" y="750"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="108"/>
- <connection refLocalId="8">
- <position x="493" y="809"/>
- <position x="435" y="809"/>
- <position x="435" y="803"/>
- <position x="379" y="803"/>
- <variable formalParameter="IN3">
- <relPosition x="0" y="167"/>
- <connection refLocalId="15">
- <position x="493" y="868"/>
- <position x="435" y="868"/>
- <position x="435" y="855"/>
- <position x="379" y="855"/>
- <variable formalParameter="IN4">
- <relPosition x="0" y="226"/>
- <connection refLocalId="28" formalParameter="CODE">
- <position x="493" y="927"/>
- <position x="379" y="927"/>
- <variable formalParameter="IN5">
- <relPosition x="0" y="285"/>
- <connection refLocalId="16">
- <position x="493" y="986"/>
- <position x="377" y="986"/>
- <variable formalParameter="OUT">
- <relPosition x="150" y="49"/>
- <inVariable localId="8" height="30" width="53">
- <position x="326" y="788"/>
- <relPosition x="53" y="15"/>
- <expression>ID</expression>
- <inVariable localId="14" height="30" width="120">
- <position x="259" y="735"/>
- <relPosition x="120" y="15"/>
- <expression>'setAttr('</expression>
- <inVariable localId="15" height="30" width="122">
- <position x="257" y="840"/>
- <relPosition x="122" y="15"/>
- <expression>',"state",'</expression>
- <inVariable localId="16" height="30" width="41">
- <position x="336" y="971"/>
- <relPosition x="41" y="15"/>
- <expression>')'</expression>
- <block localId="17" width="125" height="140" typeName="python_poll" instanceName="getstate_Command">
- <position x="801" y="1089"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="50"/>
- <connection refLocalId="18">
- <position x="801" y="1139"/>
- <position x="763" y="1139"/>
- <position x="763" y="1099"/>
- <position x="720" y="1099"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="110"/>
- <connection refLocalId="22" formalParameter="OUT">
- <position x="801" y="1199"/>
- <position x="643" y="1199"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="50"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="110"/>
- <block localId="25" width="145" height="45" typeName="STRING_TO_INT">
- <position x="966" y="1169"/>
- <variable formalParameter="IN">
- <relPosition x="0" y="30"/>
- <connection refLocalId="17" formalParameter="RESULT">
- <position x="966" y="1199"/>
- <position x="926" y="1199"/>
- <variable formalParameter="OUT">
- <relPosition x="145" y="30"/>
- <block localId="26" width="125" height="45" typeName="INT_TO_BOOL">
- <position x="1161" y="1169"/>
- <variable formalParameter="IN">
- <relPosition x="0" y="30"/>
- <connection refLocalId="25" formalParameter="OUT">
- <position x="1161" y="1199"/>
- <position x="1111" y="1199"/>
- <variable formalParameter="OUT">
- <relPosition x="125" y="30"/>
- <continuation name="CREATED" localId="18" height="30" width="110">
- <position x="610" y="1084"/>
- <relPosition x="110" y="15"/>
- <inVariable localId="19" height="30" width="53">
- <position x="383" y="1238"/>
- <relPosition x="53" y="15"/>
- <expression>ID</expression>
- <inVariable localId="20" height="30" width="150">
- <position x="286" y="1184"/>
- <relPosition x="150" y="15"/>
- <expression>'int(getAttr('</expression>
- <inVariable localId="21" height="30" width="190">
- <position x="246" y="1292"/>
- <relPosition x="190" y="15"/>
- <expression>',"state",False))'</expression>
- <block localId="22" width="150" height="183" typeName="CONCAT">
- <position x="493" y="1152"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="47"/>
- <connection refLocalId="20">
- <position x="493" y="1199"/>
- <position x="436" y="1199"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="101"/>
- <connection refLocalId="19">
- <position x="493" y="1253"/>
- <position x="436" y="1253"/>
- <variable formalParameter="IN3">
- <relPosition x="0" y="155"/>
- <connection refLocalId="21">
- <position x="493" y="1307"/>
- <position x="483" y="1307"/>
- <position x="483" y="1307"/>
- <position x="436" y="1307"/>
- <variable formalParameter="OUT">
- <relPosition x="150" y="47"/>
- <inVariable localId="23" height="30" width="130">
- <position x="300" y="355"/>
- <relPosition x="130" y="15"/>
- <expression>'",toggle='</expression>
- <block localId="24" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonToggle">
- <position x="289" y="412"/>
- <variable formalParameter="VALUE">
- <relPosition x="0" y="30"/>
- <connection refLocalId="27">
- <position x="289" y="442"/>
- <position x="220" y="442"/>
- <variable formalParameter="CODE">
- <relPosition x="140" y="30"/>
- <inVariable localId="27" height="30" width="90">
- <position x="130" y="427"/>
- <relPosition x="90" y="15"/>
- <expression>toggle</expression>
- <pou name="Led" pouType="functionBlock">
- <variable name="back_id">
- <variable name="sele_id">
- <variable name="state_in">
- <variable name="init_Command">
- <derived name="python_eval"/>
- <variable name="setstate_Command">
- <derived name="python_poll"/>
- <variable name="GetLedState">
- <derived name="GetBoolString"/>
- <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
- <position x="810" y="30"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="50"/>
- <connection refLocalId="10">
- <position x="810" y="80"/>
- <position x="753" y="80"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="110"/>
- <connection refLocalId="2" formalParameter="OUT">
- <position x="810" y="140"/>
- <position x="640" y="140"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="50"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="110"/>
- <block localId="2" width="150" height="322" typeName="CONCAT">
- <position x="490" y="90"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="50"/>
- <connection refLocalId="3">
- <position x="490" y="140"/>
- <position x="415" y="140"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="110"/>
- <connection refLocalId="11">
- <position x="490" y="200"/>
- <position x="415" y="200"/>
- <variable formalParameter="IN3">
- <relPosition x="0" y="170"/>
- <connection refLocalId="5">
- <position x="490" y="260"/>
- <position x="415" y="260"/>
- <variable formalParameter="IN4">
- <relPosition x="0" y="230"/>
- <connection refLocalId="12">
- <position x="490" y="320"/>
- <position x="414" y="320"/>
- <variable formalParameter="IN5">
- <relPosition x="0" y="290"/>
- <connection refLocalId="9">
- <position x="490" y="380"/>
- <position x="414" y="380"/>
- <variable formalParameter="OUT">
- <relPosition x="150" y="50"/>
- <inVariable localId="3" height="30" width="400">
- <position x="15" y="125"/>
- <relPosition x="400" y="15"/>
- <expression>'createSVGUIControl("button",back_id="'</expression>
- <block localId="4" width="125" height="140" typeName="python_poll" instanceName="setstate_Command">
- <position x="782" y="536"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="50"/>
- <connection refLocalId="6">
- <position x="782" y="586"/>
- <position x="653" y="586"/>
- <position x="653" y="552"/>
- <position x="602" y="552"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="110"/>
- <connection refLocalId="7" formalParameter="OUT">
- <position x="782" y="646"/>
- <position x="615" y="646"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="50"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="110"/>
- <inVariable localId="5" height="30" width="140">
- <position x="275" y="245"/>
- <relPosition x="140" y="15"/>
- <expression>'",sele_id="'</expression>
- <continuation name="CREATED" localId="6" height="30" width="110">
- <position x="492" y="537"/>
- <relPosition x="110" y="15"/>
- <block localId="7" width="150" height="319" typeName="CONCAT">
- <position x="465" y="597"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="49"/>
- <connection refLocalId="14">
- <position x="465" y="646"/>
- <position x="351" y="646"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="108"/>
- <connection refLocalId="8">
- <position x="465" y="705"/>
- <position x="407" y="705"/>
- <position x="407" y="699"/>
- <position x="351" y="699"/>
- <variable formalParameter="IN3">
- <relPosition x="0" y="167"/>
- <connection refLocalId="15">
- <position x="465" y="764"/>
- <position x="407" y="764"/>
- <position x="407" y="751"/>
- <position x="351" y="751"/>
- <variable formalParameter="IN4">
- <relPosition x="0" y="226"/>
- <connection refLocalId="28" formalParameter="CODE">
- <position x="465" y="823"/>
- <position x="351" y="823"/>
- <variable formalParameter="IN5">
- <relPosition x="0" y="285"/>
- <connection refLocalId="16">
- <position x="465" y="882"/>
- <position x="407" y="882"/>
- <position x="407" y="883"/>
- <position x="351" y="883"/>
- <variable formalParameter="OUT">
- <relPosition x="150" y="49"/>
- <inVariable localId="8" height="30" width="53">
- <position x="298" y="684"/>
- <relPosition x="53" y="15"/>
- <expression>ID</expression>
- <inVariable localId="9" height="30" width="300">
- <position x="124" y="365"/>
- <relPosition x="300" y="15"/>
- <expression>'",toggle=True,active=False)'</expression>
- <inVariable localId="10" height="30" width="70">
- <position x="683" y="65"/>
- <relPosition x="70" y="15"/>
- <expression>BOOL#1</expression>
- <inVariable localId="11" height="35" width="85">
- <position x="330" y="185"/>
- <relPosition x="85" y="15"/>
- <expression>back_id</expression>
- <inVariable localId="12" height="35" width="85">
- <position x="329" y="305"/>
- <relPosition x="85" y="15"/>
- <expression>sele_id</expression>
- <inVariable localId="14" height="30" width="120">
- <position x="231" y="631"/>
- <relPosition x="120" y="15"/>
- <expression>'setAttr('</expression>
- <inVariable localId="15" height="30" width="122">
- <position x="229" y="736"/>
- <relPosition x="122" y="15"/>
- <expression>',"state",'</expression>
- <inVariable localId="16" height="30" width="41">
- <position x="310" y="868"/>
- <relPosition x="41" y="15"/>
- <expression>')'</expression>
- <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetLedState">
- <position x="211" y="793"/>
- <variable formalParameter="VALUE">
- <relPosition x="0" y="30"/>
- <connection refLocalId="32">
- <position x="211" y="823"/>
- <position x="153" y="823"/>
- <variable formalParameter="CODE">
- <relPosition x="140" y="30"/>
- <outVariable localId="29" height="30" width="53">
- <position x="987" y="125"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="1" formalParameter="RESULT">
- <position x="987" y="140"/>
- <position x="935" y="140"/>
- <expression>ID</expression>
- <connector name="CREATED" localId="30" height="30" width="110">
- <position x="986" y="65"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="1" formalParameter="ACK">
- <position x="986" y="80"/>
- <position x="935" y="80"/>
- <inVariable localId="32" height="30" width="90">
- <position x="63" y="808"/>
- <relPosition x="90" y="15"/>
- <expression>state_in</expression>
--- a/confnodes/python/modules/svgui/pyjs/__init__.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
--- a/confnodes/python/modules/svgui/pyjs/build.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-from os.path import join, dirname, basename, abspath, split, isfile, isdir
-from optparse import OptionParser
-from cStringIO import StringIO
- from hashlib import md5
- usage: %prog [options] <application module name or path>
-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
-# -------------+-----------------------+----------------------+----------------------
-# 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",
- p = os.path.join(_data_dir, 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):
- names = os.listdir(src)
- if name.startswith('CVS'):
- if name.startswith('.git'):
- if name.startswith('.svn'):
- srcname = os.path.join(src, name)
- dstname = os.path.join(dst, name)
- if symlinks and os.path.islink(srcname):
- linkto = os.readlink(srcname)
- os.symlink(linkto, dstname)
- copytree_exists(srcname, dstname, symlinks)
- shutil.copy2(srcname, dstname)
- except (IOError, os.error), why:
- errors.append((srcname, dstname, why))
-def check_html_file(source_file, dest_path):
- """ Checks if a base HTML-file is available in the PyJamas
- 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
- 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]
- <!-- auto-generated html - you should consider editing and
- adapting this to suit your requirements
- <meta name="pygwt:module" content="%(modulename)s">
- <title>%(title)s</title>
- <script language="javascript" src="pygwt.js"></script>
- 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 ):
- os.path.join ( dest_path, mod_name + '.css' ) ) :
- css = "<link rel='stylesheet' href='" + mod_name + ".css'>"
- os.path.join ( dest_path, 'pyjamas_default.css' ) ) :
- css = "<link rel='stylesheet' href='pyjamas_default.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')
-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()
- msg += " with debugging statements"
- # 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
- if not os.path.isdir(output):
- print "Creating output directory"
- except StandardError, e:
- print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e)
- pub_dir = join(p, 'public')
- 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):
- shutil.copy(html_input_filename, html_output_filename)
- 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
- 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()
- 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)
- 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"),
- # 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(
- 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):
- print "Deleting existing app file %s" % p
- tmpl = read_boilerplate(data_dir, "all.cache.html")
- parser = pyjs.PlatformParser("platform")
- scripts = ['<script type="text/javascript" src="%s"></script>'%script \
- for script in js_includes]
- app_body = '\n'.join(scripts)
- # First, generate all the code.
- # Second, (dynamic only), post-analyse the places where modules
- # Third, write everything out.
- for platform in app_platforms:
- mod_code[platform] = {}
- mod_libs[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,
- library_modules=['dynamicajax.js',
- pover[platform].update(app_translator.overrides.items())
- for mname, name in app_translator.overrides.items():
- pd = overrides.setdefault(mname, {})
- #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
- deps = map(pyjs.strip_py, modules_to_do)
- sublist = add_subdeps(dependencies, d)
- modules_to_do += sublist
- #dependencies[app_name] = deps
- modules[platform] = modules_done + 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:
- 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,
- pover[platform].update(mod_translator.overrides.items())
- for mname, name in mod_translator.overrides.items():
- pd = overrides.setdefault(mname, {})
- mods = mod_translator.library_modules
- modules[platform] += mods
- deps = map(pyjs.strip_py, mods)
- while mod_name in deps:
- #print "modname preadd:", mod_name, deps
- sublist = add_subdeps(dependencies, d)
- modules_to_do += sublist
- modules_to_do += add_subdeps(dependencies, mod_name)
- #print "modname:", mod_name, 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])
- 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)
- mod_cache_name = "%s.cache.js" % (mod_name)
- print "Creating: " + mod_cache_name
- modlevels = make_deps(None, dependencies, dependencies[mod_name])
- 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 = "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)
- mod_cache_html_output = open(join(output, mod_cache_name), "w")
- mod_cache_html_output = StringIO()
- print >>mod_cache_html_output, mod_cache_html_template % dict(
- mod_libs = mod_libs[platform][mod_name],
- mod_cache_html_output.close()
- mod_cache_html_output.seek(0)
- app_libs_ += mod_cache_html_output.read()
- # write out the dependency ordering of the modules
- 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 = "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
- # now write app.allcache including dependency-ordered list of
- file_contents = all_cache_html_template % dict(
- early_app_libs = early_app_libs_,
- platform = platform.lower(),
- app_modnames = app_modnames,
- app_headers = app_headers
- digest = md5.new(file_contents).hexdigest()
- file_name = "%s.%s.%s" % (platform.lower(), app_name, digest)
- 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)
- app_files.append((platform.lower(), file_name))
- print "Created app file %s:%s: %s" % (
- app_name, platform, out_path)
-# creates sub-dependencies e.g. pyjamas.ui.Widget
-# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
- for i in range(0, len(m)):
- d.append('.'.join(m[:i+1]))
-def add_subdeps(deps, mod_name):
- #print "subdeps", mod_name, sd
- for i in range(0, len(sd)-1):
- l = deps.get(child, [])
-# makes unique and preserves list order
-def filter_mods(app_name, md):
- md = filter(lambda x: not x.endswith('.js'), md)
- md = map(pyjs.strip_py, md)
-def filter_deps(app_name, deps):
- for (k, l) in deps.items():
- mods = filter_mods(k, l)
-def has_nodeps(mod, deps):
- if not deps.has_key(mod) or not deps[mod]:
-def nodeps_list(mod_list, deps):
- if has_nodeps(mod, deps):
-# 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...
-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)
- for m, dl in deps.items():
- if m in deps.get(d, []):
- raise Exception('Circular Imports found: \n%s %s -> %s %s'
- #raise Exception('Could not calculate dependencies: \n%s' % 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)
- depslist = filter(lambda x: x not in nodeps, depslist)
- #print "newdeps", newdeps
- ordered_deps.append(nodeps)
- ordered_deps.append(mod_list) # last dependencies - usually the app(s)
- 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",
- 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"),
- (options, args) = parser.parse_args()
- parser.error("incorrect number of arguments")
- data_dir = abspath(options.data_dir)
- 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)
- for d in options.library_dirs:
- pyjs.path.append(abspath(d))
- 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__":
--- a/confnodes/python/modules/svgui/pyjs/jsonrpc/README.txt Tue May 08 16:31:12 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
--- a/confnodes/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-# 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
-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):
- if isinstance(service, JSONRPCService):
- service.add_method(func.__name__, func)
- emsg = 'Service "%s" not found' % str(service.__name__)
- raise NotImplementedError, emsg
-# 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
-# (r'^formsservice/$', 'djangoapp.views.processor'),
-from django import forms
- for error in form.errors.keys():
- for errorval in form.errors[error]:
- d[error].append(unicode(errorval))
-# contains the list of arguments in each field
- '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):
- field_type = field.__class__.__name__
- for n, m in field.error_messages.items():
- res['error_messages'] = msgs
- if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
- res['fields'] = map(describe_field, field.fields)
-def describe_fields_errors(fields, field_names):
- field_names = fields.keys()
- for name in field_names:
- res[name] = describe_field_errors(field)
-def describe_field(field):
- 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)
-def describe_fields(fields, field_names):
- field_names = fields.keys()
- for name in field_names:
- res[name] = describe_field(field)
-class FormProcessor(JSONRPCService):
- def __init__(self, forms, _formcls=None):
- JSONRPCService.__init__(self)
- s = FormProcessor({}, forms[k])
- self.add_method(k, s.__process)
- JSONRPCService.__init__(self, forms)
- self.formcls = _formcls
- def __process(self, request, params, command=None):
- f = self.formcls(params)
- if command is None: # just validate
- 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'):
- 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.
-# 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
-from datetime import date
-def dict_datetimeflatten(item):
- for k, v in item.items():
- if isinstance(v, datetime.date):
- elif isinstance(v, dict):
- d[k] = dict_datetimeflatten(v)
-def json_convert(l, fields=None):
- for item in serialize('python', l, fields=fields):
- res.append(dict_datetimeflatten(item))
--- a/confnodes/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-import gluon.contrib.simplejson as simplejson
-class JSONRPCServiceBase:
- 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,
- 'error': {'name': 'JSONRPCError',
- 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:
- result =self.methods[method](*params)
- return self.response(id, result)
- etype, eval, etb = sys.exc_info()
- return self.error(id, 100, '%s: %s' %(etype.__name__, eval))
- etype, eval, etb = sys.exc_info()
- return self.error(id, 100, 'Exception %s: %s' %(etype, eval))
- return self.error(id, 100, 'method "%s" does not exist' % method)
- return self.methods.keys()
--- a/confnodes/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-from pyjs.jsonrpc import JSONRPCServiceBase
-class JSONRPCService(JSONRPCServiceBase):
- return self.process(request.body.read())
- def __call__(self,func):
- self.methods[func.__name__]=func
--- a/confnodes/python/modules/svgui/pyjs/lib/_pyjs.js Tue May 08 16:31:12 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))
- 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) {
- 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 instance = new fn_cls();
- if(instance.__init__) instance.__init__.apply(instance, arguments);
- 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() {
- for (bi in fn_cls.__baseclasses)
- var b = fn_cls.__baseclasses[bi];
- if (b.__was_initialized__)
- for (bi in fn_cls.__baseclasses)
- var b = fn_cls.__baseclasses[bi];
- pyjs_extend(fn_cls, b);
- bases = [pyjslib.__Object];
- fn_cls.__baseclasses = bases;
- fn_cls.__initialize__();
- 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;
- fn_cls.prototype.__class__[k] = mth;
-function pyjs_kwargs_call(obj, func, star_args, args)
- if (!pyjslib.isIteratable(star_args))
- throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args)));
- var __i = star_args.__iter__();
- call_args[i]=__i.next();
- if (e != pyjslib.StopIteration) {
- var n = star_args.length;
- for (var i=0; i < args.length; i++) {
- call_args[n+i]=args[i];
- 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;
--- a/confnodes/python/modules/svgui/pyjs/lib/json.js Tue May 08 16:31:12 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
- var at, // The index of the current character
- ch, // The current character
-// Call error when something is wrong.
-// If a c parameter is provided, verify that it matches the current character.
- error("Expected '" + c + "' instead of '" + ch + "'");
-// Get the next character. When there are no more characters,
-// return the empty string.
-// Parse a number value.
- while (ch >= '0' && ch <= '9') {
- while (next() && ch >= '0' && ch <= '9') {
- if (ch === 'e' || ch === 'E') {
- if (ch === '-' || ch === '+') {
- while (ch >= '0' && ch <= '9') {
-// Parse a string value.
-// When parsing for string values, we must look for " and \ characters.
- } else if (ch === '\\') {
- for (i = 0; i < 4; i += 1) {
- hex = parseInt(next(), 16);
- uffff = uffff * 16 + hex;
- string += String.fromCharCode(uffff);
- } else if (typeof escapee[ch] === 'string') {
- while (ch && ch <= ' ') {
-// true, false, or null.
- error("Unexpected '" + ch + "'");
- value, // Place holder for the value function.
-// Parse an array value.
- return array; // empty array
-// Parse an object value.
- return object; // empty object
- if (Object.hasOwnProperty.call(object, key)) {
- error('Duplicate key "' + key + '"');
-// Parse a JSON value. It could be an object, an array, a string, a number,
- 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) {
-// 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
- return typeof reviver === 'function' ? (function walk(holder, key) {
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- if (Object.hasOwnProperty.call(value, k)) {
- return reviver.call(holder, key, value);
- }({'': result}, '')) : result;
--- a/confnodes/python/modules/svgui/pyjs/lib/pyjslib.py Tue May 08 16:31:12 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):
- if (module_name == "sys" || module_name == 'pyjslib')
- /*module_load_request[module_name] = 1;*/
- var override_name = sys.platform + "." + module_name;
- if (((sys.overrides != null) &&
- (sys.overrides.has_key(override_name))))
- cache_file = sys.overrides.__getitem__(override_name) ;
- cache_file = module_name ;
- cache_file = (path + cache_file + '.cache.js' ) ;
- //alert("cache " + cache_file + " " + module_name + " " + parent_module);
- 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 */
- 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
- 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+');';*/
- /* 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);*/
- if (module_name != "pyjslib" &&
-function import_wait(proceed_fn, parent_mod, dynamic) {
- var element = $doc.createElement("div");
- $doc.body.appendChild(element);
- function write_dom(txt) {
- element.innerHTML = txt + '<br />';
- var wait = function() {
- for (l in module_load_request)
- var m = module_load_request[l];
- if (l == "sys" || l == 'pyjslib')
- //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
- setTimeout(wait, timeoutperiod);
- for (l in module_load_request)
- var m = module_load_request[l];
- if (l == "sys" || l == 'pyjslib')
- module_load_request[l] = 4;
- if ((parent_mod != null) && (l == parent_mod))
- setTimeout(wait, timeoutperiod);
- /* cheat and move app on to next stage */
- module_load_request[l] = 3;
- setTimeout(wait, timeoutperiod);
- //alert("waited for module " + l + ": loaded");
- module_load_request[l] = 4;
- //alert("module wait done");
- if (proceed_fn.importDone)
- proceed_fn.importDone(proceed_fn);
- def __init__(self, path, app_modlist, app_imported_fn, dynamic,
- self.app_modlist = app_modlist
- self.app_imported_fn = app_imported_fn
- self.parent_mod = parent_mod
- 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);
- if self.idx >= len(self.app_modlist):
- import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
- import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
-def get_module(module_name):
- ev = "__mod = %s;" % module_name
-def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
- loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
- def __init__(self, *args):
- if len(self.args) is 0:
- elif len(self.args) is 1:
- return repr(self.args[0])
-class Exception(BaseException):
-class TypeError(BaseException):
-class StandardError(Exception):
-class LookupError(StandardError):
- return self.name + ": " + self.args[0]
-class KeyError(LookupError):
-class AttributeError(StandardError):
- name = "AttributeError"
- return "AttributeError: %s of %s" % (self.args[1], self.args[0])
-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;
-pyjslib.String_join = function(data) {
- if (pyjslib.isArray(data)) {
- return data.join(this);
- else if (pyjslib.isIteratable(data)) {
- var iter=data.__iter__();
- if (e != pyjslib.StopIteration) throw e;
-pyjslib.String_isdigit = function() {
- return (this.match(/^\d+$/g) != null);
-pyjslib.String_replace = function(old, replace, count) {
- if (!pyjslib.isString(old)) return this.__replace(old, replace);
- if (!pyjslib.isUndefined(count)) do_max=true;
- while (start<this.length) {
- if (do_max && !count--) break;
- pos=this.indexOf(old, start);
- new_str+=this.substring(start, pos) + replace;
- if (start<this.length) new_str+=this.substring(start);
-pyjslib.String_split = function(sep, maxsplit) {
- var items=new pyjslib.List();
- if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) {
- subject=subject.strip();
- subject=subject.replace(/\s+/g, sep);
- else if (!pyjslib.isUndefined(maxsplit)) do_max=true;
- if (subject.length == 0) {
- while (start<subject.length) {
- if (do_max && !maxsplit--) break;
- pos=subject.indexOf(sep, start);
- items.append(subject.substring(start, pos));
- if (start<=subject.length) items.append(subject.substring(start));
-pyjslib.String___iter__ = function() {
- throw pyjslib.StopIteration;
- return s.substring(i++, i, 1);
- '__iter__': function() {
-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;
- def __init__(self, name):
- if (pyjslib.hasattr(a, "__cmp__")) {
- return a.__cmp__(b) == 0;
- } else if (pyjslib.hasattr(b, "__cmp__")) {
- return b.__cmp__(a) == 0;
- if hasattr(a, "__cmp__"):
- elif hasattr(b, "__cmp__"):
- # this needs to stay in native code without any dependencies here,
- # because this is used by if and while, we need to prevent
- return v.__nonzero__();
- def __init__(self, data=None):
- def append(self, item):
- JS(""" this.l[this.l.length] = item;""")
- def extend(self, data):
- if (pyjslib.isArray(data)) {
- for (var i=0; i < data.length; i++) {
- else if (pyjslib.isIteratable(data)) {
- var iter=data.__iter__();
- if (e != pyjslib.StopIteration) throw e;
- def remove(self, value):
- var index=this.index(value);
- if (index<0) return false;
- this.l.splice(index, 1);
- def index(self, value, start=0):
- var length=this.l.length;
- for (var i=start; i<length; i++) {
- if (this.l[i]==value) {
- def insert(self, index, value):
- JS(""" var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
- def pop(self, index = -1):
- if (index<0) index = this.l.length + index;
- this.l.splice(index, 1);
- if not isinstance(l, List):
- ll = len(self) - len(l)
- for x in range(len(l)):
- ll = cmp(self.__getitem__(x), l[x])
- def slice(self, lower, upper):
- if (upper==null) return pyjslib.List(this.l.slice(lower));
- return pyjslib.List(this.l.slice(lower, upper));
- def __getitem__(self, index):
- if (index<0) index = this.l.length + index;
- def __setitem__(self, index, value):
- JS(""" this.l[index]=value;""")
- def __delitem__(self, index):
- JS(""" this.l.splice(index, 1);""")
- JS(""" return this.l.length;""")
- def __contains__(self, value):
- return self.index(value) >= 0
- throw pyjslib.StopIteration;
- '__iter__': function() {
- JS(""" this.l.reverse();""")
- def sort(self, compareFunc=None, keyFunc=None, reverse=False):
- if keyFunc and reverse:
- return -compareFunc(keyFunc(a), keyFunc(b))
- return compareFunc(keyFunc(a), keyFunc(b))
- return -compareFunc(a, b)
- self.l.sort(compareFunc)
- Access the javascript Array that is used internally by this list
- def __init__(self, data=None):
- def append(self, item):
- JS(""" this.l[this.l.length] = item;""")
- def extend(self, data):
- if (pyjslib.isArray(data)) {
- for (var i=0; i < data.length; i++) {
- else if (pyjslib.isIteratable(data)) {
- var iter=data.__iter__();
- if (e != pyjslib.StopIteration) throw e;
- def remove(self, value):
- var index=this.index(value);
- if (index<0) return false;
- this.l.splice(index, 1);
- def index(self, value, start=0):
- var length=this.l.length;
- for (var i=start; i<length; i++) {
- if (this.l[i]==value) {
- def insert(self, index, value):
- JS(""" var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
- def pop(self, index = -1):
- if (index<0) index = this.l.length + index;
- this.l.splice(index, 1);
- if not isinstance(l, Tuple):
- ll = len(self) - len(l)
- for x in range(len(l)):
- ll = cmp(self.__getitem__(x), l[x])
- def slice(self, lower, upper):
- if (upper==null) return pyjslib.Tuple(this.l.slice(lower));
- return pyjslib.Tuple(this.l.slice(lower, upper));
- def __getitem__(self, index):
- if (index<0) index = this.l.length + index;
- def __setitem__(self, index, value):
- JS(""" this.l[index]=value;""")
- def __delitem__(self, index):
- JS(""" this.l.splice(index, 1);""")
- JS(""" return this.l.length;""")
- def __contains__(self, value):
- return self.index(value) >= 0
- throw pyjslib.StopIteration;
- '__iter__': function() {
- JS(""" this.l.reverse();""")
- def sort(self, compareFunc=None, keyFunc=None, reverse=False):
- if keyFunc and reverse:
- return -compareFunc(keyFunc(a), keyFunc(b))
- return compareFunc(keyFunc(a), keyFunc(b))
- return -compareFunc(a, b)
- self.l.sort(compareFunc)
- Access the javascript Array that is used internally by this list
- def __init__(self, data=None):
- if (pyjslib.isArray(data)) {
- 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__();
- this.__setitem__(item.__getitem__(0), item.__getitem__(1));
- 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):
- var sKey = pyjslib.hash(key);
- this.d[sKey]=[key, value];
- def __getitem__(self, key):
- var sKey = pyjslib.hash(key);
- var value=this.d[sKey];
- if (pyjslib.isUndefined(value)){
- throw pyjslib.KeyError(key);
- for (var i in this.d) size++;
- def has_key(self, key):
- return self.__contains__(key)
- def __delitem__(self, key):
- var sKey = pyjslib.hash(key);
- def __contains__(self, key):
- var sKey = pyjslib.hash(key);
- return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
- var keys=new pyjslib.List();
- for (var key in this.d) {
- keys.append(this.d[key][0]);
- var values=new pyjslib.List();
- for (var key in this.d) values.append(this.d[key][1]);
- var items = new pyjslib.List();
- for (var key in this.d) {
- items.append(new pyjslib.List(kv))
- return self.keys().__iter__()
- return self.values().__iter__();
- 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):
- for k,v in d.iteritems():
- Return the javascript Object which this class uses to store
- dictionary keys and values
- return Dict(self.items())
-# taken from mochikit: range( [start,] stop[, step] )
- if (arguments.length == 2) {
- else if (arguments.length == 3) {
- else if (arguments.length>0) stop = arguments[0];
- if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
- '__iter__': function() {
-def slice(object, lower, upper):
- if (pyjslib.isString(object)) {
- lower = object.length + lower;
- 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);
- if (pyjslib.hasattr(text,"__str__")) {
- if(isString(x) and len(x) is 1):
- return x.charCodeAt(0);
- throw pyjslib.TypeError();
- return String.fromCharCode(x)
- return t == 'boolean' ||
-def get_pyjs_classtype(x):
- if (pyjslib.hasattr(x, "__class__"))
- if (pyjslib.hasattr(x.__class__, "__new__"))
- var src = x.__class__.__name__;
- """ Return the string representation of 'x'.
- //alert("repr typeof " + t + " : " + x);
- return "<function " + x.toString() + ">";
- if (x.indexOf("'") == -1)
- if (x.indexOf('"') == -1)
- var s = x.replace(new RegExp('"', "g"), '\\\\"');
- // 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();
- for (var i=0; i < contents.length; i++) {
- s += pyjslib.repr(contents[i]);
- if (i < contents.length - 1)
- if (constructor == "List") {
- var contents = x.getArray();
- for (var i=0; i < contents.length; i++) {
- s += pyjslib.repr(contents[i]);
- if (i < contents.length - 1)
- if (constructor == "Dict") {
- var keys = new Array();
- for (var i=0; i<keys.length; i++) {
- s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]);
- // If we get here, the class isn't one we know -> 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>";
- return parseFloat(text);
- return parseInt(text, radix);
- if (object==null) return 0;
- if (pyjslib.isObject(object) && object.__len__) return object.__len__();
-def isinstance(object_, classinfo):
- if pyjslib.isUndefined(object_):
- if not pyjslib.isObject(object_):
- if _isinstance(classinfo, Tuple):
- if isinstance(object_, ci):
- return _isinstance(object_, classinfo)
-def _isinstance(object_, classinfo):
- if not pyjslib.isObject(object_):
- if (object_.__class__){
- var res = object_ instanceof classinfo.constructor;
-def getattr(obj, name, default_):
- if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
- if (pyjslib.isUndefined(default_)){
- throw pyjslib.AttributeError(obj, name);
- if (!pyjslib.isFunction(obj[name])) return obj[name];
- var fnwrap = function() {
- for (var i = 0; i < arguments.length; i++) {
- args.push(arguments[i]);
- return obj[name].apply(obj,args);
- fnwrap.__name__ = name;
-def setattr(obj, name, value):
- if (!pyjslib.isObject(obj)) return null;
- if (!pyjslib.isObject(obj)) return false;
- if (pyjslib.isUndefined(obj[name])) return false;
- var properties=new pyjslib.List();
- for (property in obj) properties.append(property);
-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
- if method.call(obj, item):
-def map(obj, method, sequence=None):
- items.append(method(item))
- items.append(method.call(obj, item))
-def enumerate(sequence):
- enumeration.append([nextIndex, item])
- nextIndex = nextIndex + 1
- 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;
-# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
- return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
- return typeof a == 'function';
- return typeof a == 'string';
- return typeof a == 'object' && !a;
- return pyjslib.isObject(a) && a.constructor == Array;
- return typeof a == 'undefined';
- return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
- return typeof a == 'number' && isFinite(a);
- Convert the pyjs pythonic List and Dict objects into javascript Object and Array
- for(var k=0; k < x.length; k++) {
- var tv = pyjslib.toJSObjects(v);
- if isinstance(x, Dict):
- 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
- var tv = pyjslib.toJSObjects(v)
- if ($wnd.console==undefined) return;
- for(var i=0; i < objs.length; i++) {
-def type(clsname, bases=None, methods=None):
- """ creates a class, derived from bases, with methods and variables
- for k in methods.keys():
- JS(" var bss = null; ")
- JS(" return pyjs_type(clsname, bss, mths); ")
--- a/confnodes/python/modules/svgui/pyjs/lib/sys.py Tue May 08 16:31:12 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
-def addoverride(module_name, path):
- overrides[module_name] = path
-def addstack(linedebug):
- if (pyjslib.bool((sys.stacktrace === null))) {
- sys.stacktrace = new pyjslib.List([]);
- sys.stacktrace.append(linedebug);
- var __l = sys.stacktrace.__iter__();
- if (e != pyjslib.StopIteration) {
--- a/confnodes/python/modules/svgui/pyjs/pyjs.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1777 +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.
-from types import StringType
-from compiler import ast
-# 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.
-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):
-# this is the python function used to wrap native javascript
-NATIVE_JS_FUNC_NAME = "JS"
-PYJSLIB_BUILTIN_FUNCTIONS=("cmp",
-PYJSLIB_BUILTIN_CLASSES=("BaseException",
-def pyjs_builtin_remap(name):
-# XXX: this is a hack: these should be dealt with another way
-# however, console is currently the only global name which is causing
-PYJS_GLOBAL_VARS=("console")
-# This is taken from the django project.
-# Escape every ASCII character with a value less than 32.
- ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)])
- """Hex encodes characters for use in JavaScript strings."""
- for bad, good in JS_ESCAPES:
- value = value.replace(bad, good)
-def uuprefix(name, leave_alone=0):
- name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:])
- def __init__(self, name, name_):
- self.klasses[name] = self
- 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 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(".")
- 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);
- pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false);
- """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \
- mod_var_name_decl(importName)
- def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output,
- dynamic=0, optimize=False,
- self.module_prefix = module_name + "."
- 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.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.imported_classes = {}
- self.method_imported_globals = set()
- self.method_self = None
- self.nextTupleAssignID = 1
- self.optimize = optimize
- self.findFile = findFile
- if module_name.find(".") >= 0:
- 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)
- print >>self.output, decl
- 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, """
- var suffix="HaltException";
- if (s.length < suffix.length) {
- //alert(s + " " + suffix);
- var ss = s.substring(s.length, (s.length - suffix.length));
- //alert(s + " " + suffix + " " + ss);
- if isinstance(child, ast.Function):
- self.top_level_functions.add(child.name)
- elif isinstance(child, ast.Class):
- self.top_level_classes.add(child.name)
- if isinstance(child, ast.Function):
- self._function(child, False)
- elif isinstance(child, ast.Class):
- 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
- elif importName.endswith('.js'):
- self.imported_js.add(importName)
- 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
- self.add_imported_module(child.modname)
- 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):
- elif isinstance(child, ast.For):
- 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)
- 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:
- self.imported_modules.append(importName)
- name = importName.split(".")
- # 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!
- self.imported_modules_as.append(child_name)
- print >> self.output, gen_mod_import(self.raw_module_name,
- def _default_args_handler(self, node, arg_names, current_klass,
- output = output or self.output
- default_pos = len(arg_names) - len(node.defaults)
- if arg_names and arg_names[0] == self.method_self:
- 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)
- raise TranslationError("unsupported type (in _method)", default_node)
- default_name = arg_names[default_pos]
- 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:
- 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)
-# 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)
- #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), "]"])+";"
- 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):
- function_name = node.name
- self.add_local_arg(function_name)
- 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
- 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
- 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"
- call_name = v.node.name
- 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)
- elif isinstance(v.node.expr, ast.Getattr):
- call_name = self._getattr2(v.node.expr, current_klass, attr_name)
- elif isinstance(v.node.expr, ast.CallFunc):
- call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname
- elif isinstance(v.node.expr, ast.Subscript):
- call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname
- elif isinstance(v.node.expr, ast.Const):
- call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname
- raise TranslationError("unsupported type (in _callfunc)", v.node.expr)
- raise TranslationError("unsupported type (in _callfunc)", v.node)
- call_name = strip_py(call_name)
- star_arg_name = self.expr(v.star_args, current_klass)
- if isinstance(ch4, ast.Keyword):
- kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass)
- arg = self.expr(ch4, current_klass)
- fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args)
- fn_args = ", ".join(call_args)
- if kwargs or star_arg_name:
- try: call_this, method_name = call_name.rsplit(".", 1)
- # Must be a function call ...
- return ("pyjs_kwargs_function_call("+call_name+", "
- return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', "
- return call_name + "(" + ", ".join(call_args) + ")"
- def _print(self, node, current_klass):
- arg = self.expr(ch4, current_klass)
- 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]
- # 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 isinstance(expr, ast.Tuple):
- l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass)))
- 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)
- #print >> self.output, "} else { throw(%s); } " % errName
- print >> self.output, "}"
- 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):
- 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
- raise TranslationError("unsupported type (in _getattr)", v.expr)
- 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
- las = len(self.local_arg_stack)
- local_var_names = self.local_arg_stack[-1]
- elif v.name == "False":
- elif v.name == '__name__' and current_klass is None:
- return self.modpfx() + v.name
- elif v.name == self.method_self:
- 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:
- 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:
- elif v.name in PYJSLIB_BUILTIN_CLASSES:
- return "pyjslib." + pyjs_builtin_remap( v.name )
- 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
- cls_name_ = current_klass + "_" # XXX ???
- name = UU+cls_name_ + ".prototype.__class__." \
- if v.name == 'listener':
- name = 'listener+' + name
- def _name2(self, v, current_klass, attr_name):
- if obj in self.method_imported_globals:
- call_name = UU+self.modpfx() + obj + "." + attr_name
- elif self.imported_classes.has_key(obj):
- #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
- call_name = UU+self._name(v, current_klass) + "." + attr_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
- obj = self.expr(v.expr, current_klass)
- call_name = obj + "." + v.attrname + "." + attr_name
- def _class(self, node):
- Handle a class definition.
- In order to translate python semantics reasonably well, the following
- 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_)
- for child in node.code:
- if isinstance(child, ast.Function):
- current_klass.add_function(child.name)
- if child.name == "__init__":
- 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
- 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
- raise TranslationError("unsupported type (in _class)", node.bases[0])
- current_klass.set_base(base_class)
- raise TranslationError("more than one base (in _class)", node)
- print >>self.output, UU+class_name_ + " = function () {"
- # call superconstructor
- # print >>self.output, " __" + base_class + ".call(this);"
- print >>self.output, "}"
- 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([],
- init_method.argnames[1:],
- [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" +
- 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+" = {};"
- 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_+");"
- 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):
- 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
- 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):
- raise TranslationError("More than one expression unsupported",
- 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)
- for d in node.decorators:
- if d.name == "classmethod":
- elif d.name == "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;";
- 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) + ")"
- fexpr = UU + class_name_ + ".prototype.__class__." + node.name
- fexpr = UU + class_name_ + ".prototype." + node.name
- print >>self.output, " "+fexpr + " = function" + function_args + " {"
- self._default_args_handler(node, normal_arg_names, current_klass)
- local_arg_names = normal_arg_names + declared_arg_names
- 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)
- # Have to create a version on the instances which automatically passes the
- 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;"
- # 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';" % \
- 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:
- def _stmt(self, node, current_klass):
- debugStmt = self.debug and not self._isNativeFunc(node)
- 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):
- 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)
- raise TranslationError("unsupported type (in _stmt)", node)
- 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 " \
- + '+"\\n"+__err.name+": "+__err.message'\
- + '+"\\n\\nStack trace:\\n"' \
- 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):
- if hasattr(node, "lineno"):
- if node.lineno != None:
- 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 " \
- def _augassign(self, node, current_klass):
- 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)
- lhs = self._name(node.node, current_klass)
- 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)
- tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno)
- self._assign(tnode2, current_klass, top_level)
- if len(self.local_arg_stack) > 0:
- local_var_names = self.local_arg_stack[-1]
- def _lhsFromAttr(v, current_klass):
- if isinstance(v.expr, ast.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
- raise TranslationError("unsupported type (in _assign)", v.expr)
- def _lhsFromName(v, top_level, current_klass):
- lhs = UU+current_klass.name_ + ".prototype.__class__." \
- 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:
- self.add_local_arg(v.name)
- if v.name in local_var_names:
- elif v.name in self.method_imported_globals:
- lhs = self.modpfx() + v.name
- self.add_local_arg(v.name)
- if isinstance(v, ast.AssAttr):
- lhs = _lhsFromAttr(v, current_klass)
- if v.flags == "OP_ASSIGN":
- raise TranslationError("unsupported flag (in _assign)", v)
- elif isinstance(v, ast.AssName):
- lhs = _lhsFromName(v, top_level, current_klass)
- if v.flags == "OP_ASSIGN":
- raise TranslationError("unsupported flag (in _assign)", v)
- elif isinstance(v, ast.Subscript):
- if v.flags == "OP_ASSIGN":
- obj = self.expr(v.expr, current_klass)
- 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 + ");"
- 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 " +
- idx = self.expr(child.subs[0], current_klass)
- value = self.expr(node.expr, current_klass)
- print >>self.output, " " + obj + ".__setitem__(" \
- + idx + ", " + rhs + ");"
- print >>self.output, " " + lhs + " = " + rhs + ";"
- raise TranslationError("unsupported type (in _assign)", v)
- rhs = self.expr(node.expr, current_klass)
- 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':
- 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
- expr = self._callfunc(node.expr, current_klass)
- print >>self.output, " " + expr + ";"
- 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)
- 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]
- self._if_test(keyword, test, consequence, current_klass)
- consequence = node.else_
- self._if_test(keyword, test, consequence, current_klass)
- def _if_test(self, keyword, test, consequence, current_klass):
- expr = self.expr(test, current_klass)
- print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {"
- print >>self.output, " " + keyword + " {"
- if isinstance(consequence, ast.Stmt):
- for child in consequence.nodes:
- self._stmt(child, current_klass)
- raise TranslationError("unsupported type (in _if_test)", consequence)
- print >>self.output, " }"
- for name in node.names:
- # look up "hack" in AppTranslator as to how findFile gets here
- module_name = node.modname + "." + name[0]
- ff = self.findFile(module_name + ".py")
- self.add_imported_module(module_name)
- self.imported_classes[name[0]] = node.modname
- def _compare(self, node, current_klass):
- lhs = self.expr(node.expr, current_klass)
- raise TranslationError("only one ops supported (in _compare)", node)
- rhs_node = node.ops[0][1]
- rhs = self.expr(rhs_node, current_klass)
- return "pyjslib.eq(%s, %s)" % (lhs, rhs)
- return rhs + ".__contains__(" + lhs + ")"
- return "!" + rhs + ".__contains__(" + lhs + ")"
- 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]))+')'
- def _and(self, node, current_klass):
- expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")"
- def _for(self, node, current_klass):
- # 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":
- elif isinstance(node.assign, ast.AssTuple):
- for child in node.assign:
- child_name = child.name
- assign_name = "temp_" + child_name
- self.add_local_arg(child_name)
- var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i);
- 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)
- 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__();
- %(lhs)s %(op)s %(iterator_name)s.next();
- for node in node.body.nodes:
- self._stmt(node, current_klass)
- print >>self.output, """
- if (e.__name__ != pyjslib.StopIteration.__name__) {
- 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)
- raise TranslationError("unsupported type (in _while)", node.body)
- print >>self.output, " }"
- def _const(self, node):
- if isinstance(node.value, int):
- elif isinstance(node.value, float):
- elif isinstance(node.value, basestring):
- if isinstance(node.value, unicode):
- return "String('%s')" % escapejs(v)
- elif node.value is None:
- 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) + ")"
- raise TranslationError("must have one sub (in _subscript)", node)
- 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) + ");"
- 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):
- 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):
- raise TranslationError("varargs are not supported in Lambdas", node)
- 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,
- print >> res, 'return %s;}' % expr
- def _slice(self, node, current_klass):
- if node.flags == "OP_APPLY":
- lower = self.expr(node.lower, current_klass)
- upper = self.expr(node.upper, current_klass)
- return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")"
- 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)
- raise TranslationError("unsupported type (in expr)", node)
-def translate(file_name, module_name, debug=False):
- f = file(file_name, "r")
- output = cStringIO.StringIO()
- mod = compiler.parseFile(file_name)
- t = Translator(module_name, module_name, module_name, src, debug, mod, output)
- return output.getvalue()
- def __init__(self, platform_dir = "", verbose=True):
- self.platform_dir = platform_dir
- def setPlatform(self, platform):
- self.platform = platform
- def parseModule(self, module_name, file_name):
- if not self.parse_cache.has_key(file_name):
- mod = compiler.parseFile(file_name)
- self.parse_cache[file_name] = mod
- mod = self.parse_cache[file_name]
- 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)
- print "Importing %s (Platform %s)" % (module_name, self.platform)
- print "Importing %s" % (module_name)
- 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)
- 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)
- raise TranslationError("function not found: " + function_name, function_node)
- def replaceClassMethods(self, tree, class_name, class_node):
- # find class to replace
- for child in tree.node:
- if isinstance(child, ast.Class) and child.name == class_name:
- raise TranslationError("class not found: " + class_name, class_node)
- for function_node in class_node.code:
- if isinstance(function_node, ast.Function):
- for child in old_class_node.code:
- if isinstance(child, ast.Function) and child.name == function_node.name:
- self.copyFunction(child, function_node)
- 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
- path, ext = os.path.splitext(fname)
- return path.replace(".", "/") + ext
- def __init__(self, library_dirs=[], parser=None, dynamic=False,
- optimize=False, verbose=True):
- self.optimize = optimize
- self.library_modules = []
- self.library_dirs = path + library_dirs
- self.parser = PlatformParser()
- self.parser.dynamic = dynamic
- def findFile(self, file_name):
- if os.path.isfile(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):
- 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):
- raise Exception("file not found: " + file_name)
- def _translate(self, module_name, is_app=True, debug=False,
- 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")
- mod, override = self.parser.parseModule(module_name, file_name)
- override_name = "%s.%s" % (self.parser.platform.lower(),
- self.overrides[override_name] = override_name
- t = Translator(mn, module_name, module_name,
- src, debug, mod, output, self.dynamic, self.optimize,
- 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,
- app_code = cStringIO.StringIO()
- lib_code = cStringIO.StringIO()
- self.library_modules = []
- for library in library_modules:
- if library.endswith(".js"):
- imported_js.add(library)
- self.library_modules.append(library)
- 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'
- print >> app_code, self._translate(
- module_name, is_app, debug=debug, imported_js=imported_js)
- path = self.findFile(js)
- if os.path.isfile(path):
- 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'
- print >>sys.stderr, 'Warning: Unable to find imported javascript:', js
- return lib_code.getvalue(), app_code.getvalue()
- usage: %s file_name [module_name]
- print >> sys.stderr, usage % sys.argv[0]
- file_name = os.path.abspath(sys.argv[1])
- if not os.path.isfile(file_name):
- print >> sys.stderr, "File not found %s" % file_name
- module_name = sys.argv[2]
- print translate(file_name, module_name),
-if __name__ == "__main__":
--- a/confnodes/python/modules/svgui/svgui.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-from ConfigTree import opjimg
-from confnodes.python import PythonCodeTemplate
-from pyjs import translate
- {"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)
- # 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))
- 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())
- 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"})
-def _runtime_%(location)s_begin():
- website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
-def _runtime_%(location)s_cleanup():
-""" % {"location": location_str,
- "svgui_class": "SVGUI_HMI",
- "jsmodules" : str(jsmodules),
- res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),)
- 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())
- self.GetCTRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath)
- def _StartInkscape(self):
- svgfile = self._getSVGpath()
- if not self.GetCTRoot().CheckProjectPathPerm():
- dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
- _("You don't have write permissions.\nOpen Inkscape anyway ?"),
- wx.YES_NO|wx.ICON_QUESTION)
- open_inkscape = dialog.ShowModal() == wx.ID_YES
- if not os.path.isfile(svgfile):
--- a/confnodes/python/modules/svgui/svgui_server.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-from nevow import rend, appserver, inevow, tags, loaders, athena
-import simplejson as json
- def __init__(self, classname, id, **kwargs):
- self.classname = classname
- self.attrs = kwargs.copy()
- 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.RefreshInterface()
- def updateoutputs(self, **kwargs):
- for attrname, value in kwargs.iteritems():
- if self.outputs.get(attrname) != value:
- self.outputs[attrname] = value
- self.RefreshInterface()
- def RefreshInterface(self):
- interface = website.getHMI()
- if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit:
- d = interface.sendData(self)
- d.addCallback(self.InterfaceRefreshed)
- def InterfaceRefreshed(self, result):
- 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,
- 'kwargs': json.dumps(attrs),
-def get_object_current_state(obj):
- # Convert objects to a dictionary of their representation
- d = { '__class__': obj.classname,
- 'kwargs': json.dumps(obj.outputs),
-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):
- 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):
- return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
- def setattr(self, id, attrname, value):
- svguiWidgets[id].setinput(attrname, value)
-def createSVGUIControl(*args, **kwargs):
- gad = SvguiWidget(args[0], id, **kwargs)
- 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)
-def setAttr(id, attrname, value):
- gad = svguiWidgets.get(id, None)
- gad.setoutput(attrname, value)
-def updateAttr(id, **kwargs):
- gad = svguiWidgets.get(id, None)
- gad.updateoutput(**kwargs)
-def getAttr(id, attrname, default=None):
- gad = svguiWidgets.get(id, None)
- return gad.getinput(attrname, default)
--- a/confnodes/python/modules/svgui/svguilib.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
- def __init__(self, parent, id, args):
- 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
- self.up = not self.state
- # Add event on each element of the button
- 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)
- # method to display the current state of interface
- def updateElements(self):
- self.sele_elt.setAttribute("display", "none")
- self.back_elt.removeAttribute("display")
- 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)
- def handleEvent(self, evt):
- # Quand le bouton de la souris est presse
- if evt.type == "mousedown":
- updateAttr(self.id, 'state', self.state)
- if isCurrentObject(self) and self.dragging:
- # Quand le bouton est survole
- if evt.type == "mouseover" and self.toggle:
- # Quand le curseur quitte la zone du bouton
- elif evt.type == "mouseout" and self.toggle:
- self.up = not self.state
- # Quand le bouton de la souris est relache
- elif evt.type == "mouseup":
- if self.toggle and self.up == self.state:
- self.state = not self.state
- updateAttr(self.id, 'state', self.state)
- updateAttr(self.id, 'state', self.state)
- def __init__(self, parent, id, args):
- self.back_elt = getSVGElementById(args.back_id)
- if args.text != undefined:
- def updateValues(self, values):
- if values.text != self.value:
- self.text = values.text
- updateAttr(self.id, 'text', self.text)
- def updateElements(self):
- self.back_elt.firstChild.firstChild.textContent = self.text
- def handleEvent(self, evt):
\ No newline at end of file
--- a/confnodes/python/modules/wxglade_hmi/README Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
\ No newline at end of file
--- a/confnodes/python/modules/wxglade_hmi/__init__.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from wxglade_hmi import *
--- a/confnodes/python/modules/wxglade_hmi/wxglade_hmi.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-from xml.dom import minidom
-from ConfigTree import opjimg
-from confnodes.python import PythonCodeTemplate
-class RootClass(PythonCodeTemplate):
- {"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__':
- 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')
- wxgfile_path=self._getWXGLADEpath()
- if os.path.exists(wxgfile_path):
- wxgfile = open(wxgfile_path, 'r')
- wxgtree = minidom.parse(wxgfile)
- 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
- 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())
- runtimefile.write(self.GetPythonCode())
-def _runtime_%(location)s_begin():
- wx.MessageBox(_("Please stop PLC to close"))
-def _runtime_%(location)s_cleanup():
-""" % {"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": x[0], "class": x[1]},
- "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))})
- return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
- def _editWXGLADE(self):
- wxg_filename = self._getWXGLADEpath()
- if not self.GetCTRoot().CheckProjectPathPerm():
- dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
- _("You don't have write permissions.\nOpen wxGlade anyway ?"),
- wx.YES_NO|wx.ICON_QUESTION)
- open_wxglade = dialog.ShowModal() == wx.ID_YES
- if not os.path.exists(wxg_filename):
- hmi_name = self.BaseParams.getName()
- open(wxg_filename,"w").write("""<?xml version="1.0"?>
- <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
- <object class="%(class)s" name="%(name)s" base="EditFrame">
- <style>wxDEFAULT_FRAME_STYLE</style>
- """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
- if wx.Platform == '__WXMSW__':
- wxg_filename = "\"%s\""%wxg_filename
- self.launch_wxglade([wxg_filename])
--- a/confnodes/python/plc_python.c Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
- * Python Asynchronous execution code
- * PLC put python commands in a fifo, respecting execution order
- * with the help of C pragmas inserted in python_eval FB code
- * Buffer content is read asynchronously, (from non real time part),
- * commands are executed and result stored for later use by PLC.
- * In this implementation, fifo is a list of pointer to python_eval
- * function blocks structures. Some local variables have been added in
- * python_eval interface. We use those local variables as buffer and state
-#include "iec_types_all.h"
-/* The fifo (fixed size, as number of FB is fixed) */
-static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d];
-/* Producer and consumer cursors */
-static int Current_PLC_EvalFB;
-static int Current_Python_EvalFB;
-/* A global IEC-Python gateway state, for use inside python_eval FBs*/
-#define PYTHON_LOCKED_BY_PYTHON 0
-#define PYTHON_LOCKED_BY_PLC 1
-#define PYTHON_MUSTWAKEUP 2
-#define PYTHON_FINISHED 4
-/* Each python_eval FunctionBlock have it own state */
-#define PYTHON_FB_FREE 0
-#define PYTHON_FB_REQUESTED 1
-#define PYTHON_FB_PROCESSING 2
-#define PYTHON_FB_ANSWERED 3
-int WaitPythonCommands(void);
-void UnBlockPythonCommands(void);
-int TryLockPython(void);
-void UnLockPython(void);
-int __init_%(location)s()
- /* Initialize cursors */
- Current_Python_EvalFB = 0;
- Current_PLC_EvalFB = 0;
- PythonState = PYTHON_LOCKED_BY_PYTHON;
- for(i = 0; i < %(python_eval_fb_count)d; i++)
-void __cleanup_%(location)s()
- PythonState = PYTHON_FINISHED;
- UnBlockPythonCommands();
-void __retrieve_%(location)s()
- /* Check Python thread is not being
- * modifying internal python_eval data */
- PythonState = TryLockPython() ?
- PYTHON_LOCKED_BY_PYTHON;
- /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
- * and python_eval will no do anything */
-void __publish_%(location)s()
- if(PythonState & PYTHON_LOCKED_BY_PLC){
- /* If runnig PLC did push something in the fifo*/
- if(PythonState & PYTHON_MUSTWAKEUP){
- /* WakeUp python thread */
- UnBlockPythonCommands();
- * Called by the PLC, each time a python_eval
- * FB instance is executed
-void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
- /* detect rising edge on TRIG to trigger evaluation */
- if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) ||
- /* polling is equivalent to trig on value rather than on rising edge*/
- (poll && __GET_VAR(data__->TRIG) )) &&
- /* trig only if not already trigged */
- __GET_VAR(data__->TRIGGED) == 0){
- __SET_VAR(data__->, TRIGGED, 1);
- /* make a safe copy of the code */
- __SET_VAR(data__->, PREBUFFER, __GET_VAR(data__->CODE));
- /* retain value for next rising edge detection */
- __SET_VAR(data__->, TRIGM1, __GET_VAR(data__->TRIG));
- /* python thread is not in ? */
- if( PythonState & PYTHON_LOCKED_BY_PLC){
- /* if some answer are waiting, publish*/
- if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){
- /* Copy buffer content into result*/
- __SET_VAR(data__->, RESULT, __GET_VAR(data__->BUFFER));
- /* signal result presece to PLC*/
- __SET_VAR(data__->, ACK, 1);
- __SET_VAR(data__->, STATE, PYTHON_FB_FREE);
- /* mark as not trigged */
- __SET_VAR(data__->, TRIGGED, 0);
- /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
- /* when in polling, no answer == ack down */
- __SET_VAR(data__->, ACK, 0);
- /* got the order to act ?*/
- if(__GET_VAR(data__->TRIGGED) == 1 &&
- /* and not already being processed */
- __GET_VAR(data__->STATE) == PYTHON_FB_FREE)
- /* Enter the block in the fifo
- * Don't have to check if fifo cell is free
- * as fifo size == FB count, and a FB cannot
- * be requested twice */
- EvalFBs[Current_PLC_EvalFB] = data__;
- /* copy into BUFFER local*/
- __SET_VAR(data__->, BUFFER, __GET_VAR(data__->PREBUFFER));
- /* Set ACK pin to low so that we can set a rising edge on result */
- /* when not polling, a new answer imply reseting ack*/
- __SET_VAR(data__->, ACK, 0);
- /* when in polling, acting reset trigger */
- __SET_VAR(data__->, TRIGGED, 0);
- __SET_VAR(data__->, STATE, PYTHON_FB_REQUESTED);
- /* Have to wakeup python thread in case he was asleep */
- PythonState |= PYTHON_MUSTWAKEUP;
- /*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
- Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
-char* PythonIterator(char* result)
- //printf("PythonIterator result %%s\n", result);
- if(PythonState & PYTHON_FINISHED) return NULL;
- /* take python mutex to prevent changing PLC data while PLC running */
- data__ = EvalFBs[Current_Python_EvalFB];
- if(data__ && /* may be null at first run */
- __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/
- /* If result not None */
- __SET_VAR(data__->, BUFFER, strlen(result), .len);
- /* prevent results overrun */
- if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN)
- __SET_VAR(data__->, BUFFER, STR_MAX_LEN, .len );
- /* TODO : signal error */
- /* Copy results to buffer */
- strncpy((char*)__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len));
- __SET_VAR(data__->, BUFFER, 0, .len);
- /* remove block from fifo*/
- EvalFBs[Current_Python_EvalFB] = NULL;
- /* Mark block as answered */
- __SET_VAR(data__->, STATE, PYTHON_FB_ANSWERED);
- Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
- //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
- /* while next slot is empty */
- while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
- /* or doesn't contain command */
- __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED)
- /* wait next FB to eval */
- //printf("PythonIterator wait\n");
- if(WaitPythonCommands()) return NULL;
- if(PythonState & PYTHON_FINISHED) return NULL;
- /* Mark block as processing */
- __SET_VAR(data__->, STATE, PYTHON_FB_PROCESSING);
- //printf("PythonIterator\n");
- /* make BUFFER a null terminated string */
- __SET_VAR(data__->, BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]);
- /* next command is BUFFER */
- next_command = (char*)__GET_VAR(data__->BUFFER, .body);
- /* free python mutex */
- /* return the next command to eval */
--- a/confnodes/python/pous.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="http://www.plcopen.org/xml/tc6.xsd"
- xmlns:xhtml="http://www.w3.org/1999/xhtml"
- xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
- <fileHeader companyName="Beremiz"
- creationDateTime="2008-12-14T16:53:26"/>
- <contentHeader name="Beremiz non-standard POUs library"
- modificationDateTime="2008-12-23T22:35:46">
- <pou name="python_eval" pouType="functionBlock">
- <variable name="RESULT">
- <variable name="STATE">
- <variable name="BUFFER">
- <variable name="PREBUFFER">
- <variable name="TRIGM1">
- <variable name="TRIGGED">
-<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(0, data__);}]]>
- <pou name="python_poll" pouType="functionBlock">
- <variable name="RESULT">
- <variable name="STATE">
- <variable name="BUFFER">
- <variable name="PREBUFFER">
- <variable name="TRIGM1">
- <variable name="TRIGGED">
-<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(1,(PYTHON_EVAL*)(void*)data__);}]]>
- <pou name="python_gear" pouType="functionBlock">
- <variable name="RESULT">
- <variable name="py_eval">
- <derived name="python_eval"/>
- <variable name="COUNTER">
- <block localId="1" width="125" height="110" typeName="python_eval" instanceName="py_eval">
- <position x="525" y="580"/>
- <variable formalParameter="TRIG">
- <relPosition x="0" y="40"/>
- <connection refLocalId="7" formalParameter="OUT">
- <position x="525" y="620"/>
- <position x="495" y="620"/>
- <position x="495" y="575"/>
- <position x="465" y="575"/>
- <variable formalParameter="CODE">
- <relPosition x="0" y="85"/>
- <connection refLocalId="4">
- <position x="525" y="665"/>
- <position x="370" y="665"/>
- <variable formalParameter="ACK">
- <relPosition x="125" y="40"/>
- <variable formalParameter="RESULT">
- <relPosition x="125" y="85"/>
- <inVariable localId="2" height="35" width="25">
- <position x="435" y="270"/>
- <relPosition x="25" y="15"/>
- <expression>N</expression>
- <inVariable localId="3" height="35" width="55">
- <position x="275" y="585"/>
- <relPosition x="55" y="15"/>
- <expression>TRIG</expression>
- <inVariable localId="4" height="35" width="55">
- <position x="315" y="650"/>
- <relPosition x="55" y="15"/>
- <expression>CODE</expression>
- <outVariable localId="5" height="35" width="45">
- <position x="740" y="605"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="1" formalParameter="ACK">
- <position x="740" y="620"/>
- <position x="650" y="620"/>
- <expression>ACK</expression>
- <outVariable localId="6" height="35" width="75">
- <position x="740" y="650"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="1" formalParameter="RESULT">
- <position x="740" y="665"/>
- <position x="650" y="665"/>
- <expression>RESULT</expression>
- <block localId="7" width="80" height="65" typeName="AND">
- <position x="385" y="545"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="30"/>
- <connection refLocalId="13" formalParameter="OUT">
- <position x="385" y="575"/>
- <position x="335" y="575"/>
- <position x="335" y="455"/>
- <position x="625" y="455"/>
- <position x="625" y="285"/>
- <position x="615" y="285"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="55"/>
- <connection refLocalId="3">
- <position x="385" y="600"/>
- <position x="330" y="600"/>
- <variable formalParameter="OUT">
- <relPosition x="80" y="30"/>
- <inVariable localId="9" height="35" width="85">
- <position x="240" y="330"/>
- <relPosition x="85" y="15"/>
- <expression>COUNTER</expression>
- <block localId="10" width="80" height="65" typeName="ADD">
- <position x="380" y="330"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="30"/>
- <connection refLocalId="9">
- <position x="380" y="360"/>
- <position x="352" y="360"/>
- <position x="352" y="345"/>
- <position x="325" y="345"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="55"/>
- <connection refLocalId="11">
- <position x="380" y="385"/>
- <position x="325" y="385"/>
- <variable formalParameter="OUT">
- <relPosition x="80" y="30"/>
- <inVariable localId="11" height="35" width="85">
- <position x="240" y="370"/>
- <relPosition x="85" y="15"/>
- <expression>USINT#1</expression>
- <block localId="13" width="80" height="65" typeName="EQ">
- <position x="535" y="255"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="30"/>
- <connection refLocalId="2">
- <position x="535" y="285"/>
- <position x="460" y="285"/>
- <variable formalParameter="IN2">
- <relPosition x="0" y="55"/>
- <connection refLocalId="10" formalParameter="OUT">
- <position x="535" y="310"/>
- <position x="497" y="310"/>
- <position x="497" y="360"/>
- <position x="460" y="360"/>
- <variable formalParameter="OUT">
- <relPosition x="80" y="30"/>
- <block localId="15" width="80" height="135" typeName="SEL">
- <position x="785" y="245"/>
- <variable formalParameter="G">
- <relPosition x="0" y="40"/>
- <connection refLocalId="13" formalParameter="OUT">
- <position x="785" y="285"/>
- <position x="615" y="285"/>
- <variable formalParameter="IN0">
- <relPosition x="0" y="75"/>
- <connection refLocalId="10" formalParameter="OUT">
- <position x="785" y="320"/>
- <position x="650" y="320"/>
- <position x="650" y="360"/>
- <position x="460" y="360"/>
- <variable formalParameter="IN1">
- <relPosition x="0" y="115"/>
- <connection refLocalId="16">
- <position x="785" y="360"/>
- <position x="760" y="360"/>
- <variable formalParameter="OUT">
- <relPosition x="80" y="40"/>
- <inVariable localId="16" height="35" width="85">
- <position x="675" y="345"/>
- <relPosition x="85" y="15"/>
- <expression>USINT#0</expression>
- <outVariable localId="17" height="35" width="85">
- <position x="905" y="270"/>
- <relPosition x="0" y="15"/>
- <connection refLocalId="15" formalParameter="OUT">
- <position x="905" y="285"/>
- <position x="865" y="285"/>
- <expression>COUNTER</expression>
--- a/confnodes/python/python.py Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-from ConfigTree import ConfigTreeNode, opjimg
-from PLCControler import UndoBuffer
-from PythonEditor import PythonEditor
-from xml.dom import minidom
-PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd"))
-class PythonCodeTemplate:
- EditorType = PythonEditor
- 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)
- 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)
- self.CreatePythonBuffer(False)
- def ConfNodePath(self):
- return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType)
- def PythonFileName(self):
- return os.path.join(self.CTNPath(), "python.xml")
- if self.PythonBuffer.IsCurrentSaved():
- 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()
- filepath = self.PythonFileName()
- text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
- extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
- "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
- "xsi:schemaLocation" : "python_xsd.xsd"}
- text += self.PythonCode.generateXMLText("Python", 0, extras)
- xmlfile = open(filepath,"w")
- xmlfile.write(text.encode("utf-8"))
- self.MarkPythonAsSaved()
-#-------------------------------------------------------------------------------
-# Current Buffering Management Functions
-#-------------------------------------------------------------------------------
- Return a copy of the project
- return cPickle.loads(cPickle.dumps(model))
- def CreatePythonBuffer(self, saved):
- self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
- def BufferPython(self):
- self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
- def StartBuffering(self):
- def EndBuffering(self):
- self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
- def MarkPythonAsSaved(self):
- self.PythonBuffer.CurrentSaved()
- def PythonIsSaved(self):
- return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
- def LoadPrevious(self):
- self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
- 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):
- __import__("confnodes.python.modules." + name)
- return getattr(modules, name).RootClass
-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):
- @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.GetIECProgramsAndVariables()
- 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:
- 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))
- plc_python_code = plc_python_code % {
- "python_eval_fb_count": python_eval_fb_count,
- "location": location_str}
- Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str)
- pythonfile = open(Gen_Pythonfile_path,'w')
- pythonfile.write(plc_python_code)
- runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
- runtimefile = open(runtimefile_path, 'w')
- runtimefile.write(self.GetPythonCode())
- 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"))
--- a/confnodes/python/python_xsd.xsd Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<xsd:schema targetNamespace="python_xsd.xsd"
- xmlns:cext="python_xsd.xsd"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified">
- <xsd:element name="Python">
- <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
- <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/features.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,7 @@
+from os import listdir, path + ('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')] --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/PythonEditor.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,505 @@
+from controls import EditorPanel +if wx.Platform == '__WXMSW__': + faces = { 'times': 'Times New Roman', + 'mono' : 'Courier New', + 'other': 'Comic Sans MS', +elif wx.Platform == '__WXMAC__': + faces = { 'times': 'Times New Roman', + 'other': 'Comic Sans MS', + faces = { 'times': 'Times', + 'other': 'new century schoolbook', +] = [wx.NewId() for _init_ctrls in range(1)] +def GetCursorPos(old, new): + common_length = min(old_length, new_length) + for i in xrange(common_length): + if old_length < new_length: + if common_length > 0 and old[i] != new[i]: + return i + new_length - old_length + return i + new_length - old_length + 1 + elif old_length > new_length or i < min(old_length, new_length) - 1: + if common_length > 0 and old[i] != new[i]: +class PythonEditor(EditorPanel): + def _init_Editor(self, prnt): + self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt, + name="TextViewer", pos=wx.DefaultPosition, + size=wx.DefaultSize, style=0) + self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN) + self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT) + self.Editor.SetLexer(stc.STC_LEX_PYTHON) + self.Editor.SetKeyWords(0, " ".join(keyword.kwlist)) + self.Editor.SetProperty("fold", "1") + self.Editor.SetProperty("tab.timmy.whinge.level", "1") + self.Editor.SetMargins(0,0) + self.Editor.SetViewWhiteSpace(False) + self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND) + self.Editor.SetEdgeColumn(78) + # Set up the numbers in the margin for margin #1 + self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) + # Reasonable value for, say, 4-5 digits using a mono font (40 pix) + self.Editor.SetMarginWidth(1, 40) + # Setup a margin to hold fold markers + self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL) + self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS) + self.Editor.SetMarginSensitive(2, True) + self.Editor.SetMarginWidth(2, 12) + if self.fold_symbols == 0: + # Arrow pointing right for contracted folders, arrow pointing down for expanded + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") + elif self.fold_symbols == 1: + # Plus for contracted folders, minus for expanded + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") + elif self.fold_symbols == 2: + # Like a flattened tree control using circular headers and curved joins + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") + elif self.fold_symbols == 3: + # Like a flattened tree control using square headers + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080") + self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080") + self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) + self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) + self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed) + if wx.Platform == '__WXMSW__': + self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New') + elif wx.Platform == '__WXMAC__': + # TODO: if this looks fine on Linux too, remove the Mac-specific case + # and use this whenever OS != MSW. + self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco') + defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize() + self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize) + # Clear styles and revert to default. + self.Editor.StyleClearAll() + # Following style specs only indicate differences from default. + # The rest remains unchanged. + # Line numbers in margin + self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') + self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') + self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') + self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") + self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000') + self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') + self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') + self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080') + # Strings and characters + self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080') + self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080') + self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold') + self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') + self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') + self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') + self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold') + self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold') + # Identifiers. I leave this as not bold because everything seems + # to be an identifier if it doesn't match the above criterae + self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000') + self.Editor.SetCaretForeground("BLUE") + self.Editor.SetSelBackground(1, '#66CCFF') + self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)) + self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)) + # register some images for use in the AutoComplete box. + #self.RegisterImage(1, images.getSmilesBitmap()) + self.Editor.RegisterImage(1, + wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) + self.Editor.RegisterImage(2, + wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16))) + self.Editor.RegisterImage(3, + wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16))) + # Indentation and tab stuff + self.Editor.SetIndent(4) # Proscribed indent size for wx + self.Editor.SetIndentationGuides(True) # Show indent guides + self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space + self.Editor.SetTabIndents(True) # Tab key indents + self.Editor.SetTabWidth(4) # Proscribed tab size for wx + self.Editor.SetUseTabs(False) # Use spaces rather than tabs, or + # TabTimmy will complain! + self.Editor.SetViewWhiteSpace(False) # Don't view white space + # EOL: Since we are loading/saving ourselves, and the + # strings will always have \n's in them, set the STC to + self.Editor.SetEOLMode(wx.stc.STC_EOL_LF) + self.Editor.SetViewEOL(False) + # No right-edge mode indicator + self.Editor.SetEdgeMode(stc.STC_EDGE_NONE) + self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) + self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR) + self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR) + def __init__(self, parent, controler, window): + EditorPanel.__init__(self, parent, "", window, controler) + self.DisableEvents = False + self.CurrentAction = None + img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() + self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) + self.Controler.OnCloseEditor(self) + fullname = self.Controler.CTNFullName() + if not self.Controler.PythonIsSaved(): + return "~%s~" % fullname + def GetBufferState(self): + return self.Controler.GetBufferState() + self.Controler.LoadPrevious() + self.Controler.LoadNext() + def OnModification(self, event): + if not self.DisableEvents: + mod_type = event.GetModificationType() + if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO): + if mod_type&wx.stc.STC_MOD_BEFOREINSERT: + if self.CurrentAction is None: + elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1: + self.Controler.EndBuffering() + self.CurrentAction = ("Add", event.GetPosition()) + wx.CallAfter(self.RefreshModel) + elif mod_type&wx.stc.STC_MOD_BEFOREDELETE: + if self.CurrentAction == None: + elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1: + self.Controler.EndBuffering() + self.CurrentAction = ("Delete", event.GetPosition()) + wx.CallAfter(self.RefreshModel) + def OnDoDrop(self, event): + wx.CallAfter(self.RefreshModel) + # Buffer the last model state + def RefreshBuffer(self): + self.Controler.BufferPython() + if self.ParentWindow is not None: + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshFileMenu() + self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshPageTitles() + def StartBuffering(self): + self.Controler.StartBuffering() + if self.ParentWindow is not None: + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshFileMenu() + self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshPageTitles() + if self.CurrentAction != None: + self.Controler.EndBuffering() + self.CurrentAction = None + self.DisableEvents = True + old_cursor_pos = self.Editor.GetCurrentPos() + old_text = self.Editor.GetText() + new_text = self.Controler.GetPythonCode() + self.Editor.SetText(new_text) + new_cursor_pos = GetCursorPos(old_text, new_text) + if new_cursor_pos != None: + self.Editor.GotoPos(new_cursor_pos) + self.Editor.GotoPos(old_cursor_pos) + self.Editor.ScrollToColumn(0) + self.Editor.EmptyUndoBuffer() + self.DisableEvents = False + self.Editor.Colourise(0, -1) + def RefreshModel(self): + self.Controler.SetPythonCode(self.Editor.GetText()) + def OnKeyPressed(self, event): + if self.Editor.CallTipActive(): + self.Editor.CallTipCancel() + key = event.GetKeyCode() + if key == 32 and event.ControlDown(): + pos = self.Editor.GetCurrentPos() +## self.CallTipSetBackground("yellow") +## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n' +## 'show some suff, maybe parameters..\n\n' +## 'fubar(param1, param2)') + self.Editor.AutoCompSetIgnoreCase(False) # so this needs to match + # Images are specified with a appended "?type" + self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist])) + def OnKillFocus(self, event): + self.Editor.AutoCompCancel() + def OnUpdateUI(self, evt): + # check for matching braces + caretPos = self.Editor.GetCurrentPos() + charBefore = self.Editor.GetCharAt(caretPos - 1) + styleBefore = self.Editor.GetStyleAt(caretPos - 1) + if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR: + braceAtCaret = caretPos - 1 + charAfter = self.Editor.GetCharAt(caretPos) + styleAfter = self.Editor.GetStyleAt(caretPos) + if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR: + braceAtCaret = caretPos + braceOpposite = self.Editor.BraceMatch(braceAtCaret) + if braceAtCaret != -1 and braceOpposite == -1: + self.Editor.BraceBadLight(braceAtCaret) + self.Editor.BraceHighlight(braceAtCaret, braceOpposite) + #pt = self.Editor.PointFromPosition(braceOpposite) + #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5)) + #self.Editor.Refresh(False) + def OnMarginClick(self, evt): + # fold and unfold as needed + if evt.GetMargin() == 2: + if evt.GetShift() and evt.GetControl(): + lineClicked = self.Editor.LineFromPosition(evt.GetPosition()) + if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: + self.Editor.SetFoldExpanded(lineClicked, True) + self.Expand(lineClicked, True, True, 1) + if self.Editor.GetFoldExpanded(lineClicked): + self.Editor.SetFoldExpanded(lineClicked, False) + self.Expand(lineClicked, False, True, 0) + self.Editor.SetFoldExpanded(lineClicked, True) + self.Expand(lineClicked, True, True, 100) + self.Editor.ToggleFold(lineClicked) + lineCount = self.Editor.GetLineCount() + # find out if we are folding or unfolding + for lineNum in range(lineCount): + if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: + expanding = not self.Editor.GetFoldExpanded(lineNum) + while lineNum < lineCount: + level = self.Editor.GetFoldLevel(lineNum) + if level & stc.STC_FOLDLEVELHEADERFLAG and \ + (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: + self.Editor.SetFoldExpanded(lineNum, True) + lineNum = self.Expand(lineNum, True) + lastChild = self.Editor.GetLastChild(lineNum, -1) + self.Editor.SetFoldExpanded(lineNum, False) + if lastChild > lineNum: + self.Editor.HideLines(lineNum+1, lastChild) + def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): + lastChild = self.Editor.GetLastChild(line, level) + while line <= lastChild: + self.Editor.ShowLines(line, line) + self.Editor.HideLines(line, line) + self.Editor.ShowLines(line, line) + level = self.Editor.GetFoldLevel(line) + if level & stc.STC_FOLDLEVELHEADERFLAG: + self.Editor.SetFoldExpanded(line, True) + self.Editor.SetFoldExpanded(line, False) + line = self.Expand(line, doExpand, force, visLevels-1) + if doExpand and self.Editor.GetFoldExpanded(line): + line = self.Expand(line, True, force, visLevels-1) + line = self.Expand(line, False, force, visLevels-1) + self.DisableEvents = True + self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT) + self.DisableEvents = False + self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY) + self.DisableEvents = True + self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE) + self.DisableEvents = False --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/README Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+Asynchronous Python Interpreter --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/__init__.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/__init__.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,13 @@
+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("__")] + helpfilename = path.join(_base_path, name, "README") + if path.isfile(helpfilename): + helps.append(open(helpfilename).readline().strip()) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/README Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/__init__.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/livesvg.js Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,59 @@
+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) { +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] + gadget.updateValues(json_parse(dataReceived.kwargs)); + //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState); + function init(self, arg1){ + //console.log("Object received : " + 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); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pous.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1428 @@
+<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://www.plcopen.org/xml/tc6.xsd" + xmlns:xhtml="http://www.w3.org/1999/xhtml" + xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd"> + <fileHeader companyName="Beremiz" + creationDateTime="2008-12-14T16:53:26"/> + <contentHeader name="Beremiz non-standard POUs library" + modificationDateTime="2009-08-12T15:35:33"> + <pou name="GetBoolString" pouType="functionBlock"> + <variable name="VALUE"> + <pou name="TextCtrl" pouType="functionBlock"> + <variable name="back_id"> + <variable name="set_text"> + <variable name="SVGUI_TEXTCTRL"> + <derived name="python_eval"/> + <variable name="setstate_Command"> + <derived name="python_eval"/> + <block localId="1" width="193" height="160" typeName="CONCAT"> + <position x="626" y="122"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="43"/> + <connection refLocalId="2"> + <position x="626" y="165"/> + <position x="535" y="165"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="89"/> + <connection refLocalId="3"> + <position x="626" y="211"/> + <position x="535" y="211"/> + <variable formalParameter="IN3"> + <relPosition x="0" y="135"/> + <connection refLocalId="6"> + <position x="626" y="257"/> + <position x="532" y="257"/> + <variable formalParameter="OUT"> + <relPosition x="193" y="43"/> + <inVariable localId="2" height="30" width="460"> + <position x="75" y="150"/> + <relPosition x="460" y="15"/> + <expression>'createSVGUIControl("textControl", back_id="'</expression> + <inVariable localId="3" height="35" width="85"> + <position x="450" y="196"/> + <relPosition x="85" y="15"/> + <expression>back_id</expression> + <inVariable localId="6" height="30" width="50"> + <position x="482" y="242"/> + <relPosition x="50" y="15"/> + <expression>'")'</expression> + <block localId="7" width="125" height="115" typeName="python_eval" instanceName="SVGUI_TEXTCTRL"> + <position x="909" y="75"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="45"/> + <connection refLocalId="9"> + <position x="909" y="120"/> + <position x="886" y="120"/> + <position x="886" y="85"/> + <position x="869" y="85"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="90"/> + <connection refLocalId="1" formalParameter="OUT"> + <position x="909" y="165"/> + <position x="819" y="165"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="45"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="90"/> + <inVariable localId="9" height="30" width="70"> + <position x="799" y="70"/> + <relPosition x="70" y="15"/> + <expression>BOOL#1</expression> + <outVariable localId="10" height="30" width="30"> + <position x="1094" y="150"/> + <relPosition x="0" y="15"/> + <connection refLocalId="7" formalParameter="RESULT"> + <position x="1094" y="165"/> + <position x="1034" y="165"/> + <expression>ID</expression> + <connector name="CREATED" localId="11" height="30" width="110"> + <position x="1096" y="105"/> + <relPosition x="0" y="15"/> + <connection refLocalId="7" formalParameter="ACK"> + <position x="1096" y="120"/> + <position x="1034" y="120"/> + <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command"> + <position x="957" y="472"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="50"/> + <connection refLocalId="31" formalParameter="OUT"> + <position x="957" y="522"/> + <position x="909" y="522"/> + <position x="909" y="444"/> + <position x="857" y="444"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="110"/> + <connection refLocalId="12" formalParameter="OUT"> + <position x="957" y="582"/> + <position x="822" y="582"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="50"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="110"/> + <continuation name="CREATED" localId="5" height="30" width="110"> + <position x="589" y="429"/> + <relPosition x="110" y="15"/> + <block localId="12" width="186" height="288" typeName="CONCAT"> + <position x="636" y="536"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="46"/> + <connection refLocalId="14"> + <position x="636" y="582"/> + <position x="526" y="582"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="99"/> + <connection refLocalId="8"> + <position x="636" y="635"/> + <position x="526" y="635"/> + <variable formalParameter="IN3"> + <relPosition x="0" y="152"/> + <connection refLocalId="15"> + <position x="636" y="688"/> + <position x="527" y="688"/> + <variable formalParameter="IN4"> + <relPosition x="0" y="205"/> + <connection refLocalId="32"> + <position x="636" y="741"/> + <position x="528" y="741"/> + <variable formalParameter="IN5"> + <relPosition x="0" y="258"/> + <connection refLocalId="16"> + <position x="636" y="794"/> + <position x="528" y="794"/> + <variable formalParameter="OUT"> + <relPosition x="186" y="46"/> + <inVariable localId="8" height="30" width="53"> + <position x="473" y="620"/> + <relPosition x="53" y="15"/> + <expression>ID</expression> + <inVariable localId="13" height="35" width="100"> + <position x="599" y="469"/> + <relPosition x="100" y="17"/> + <expression>set_text</expression> + <inVariable localId="14" height="30" width="120"> + <position x="406" y="567"/> + <relPosition x="120" y="15"/> + <expression>'setAttr('</expression> + <inVariable localId="15" height="30" width="122"> + <position x="405" y="673"/> + <relPosition x="122" y="15"/> + <expression>',"text","'</expression> + <inVariable localId="16" height="30" width="50"> + <position x="478" y="779"/> + <relPosition x="50" y="15"/> + <expression>'")'</expression> + <block localId="31" width="75" height="105" typeName="AND"> + <position x="782" y="403"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="41"/> + <connection refLocalId="5"> + <position x="782" y="444"/> + <position x="699" y="444"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="83"/> + <connection refLocalId="13"> + <position x="782" y="486"/> + <position x="699" y="486"/> + <variable formalParameter="OUT"> + <relPosition x="75" y="41"/> + <inVariable localId="32" height="30" width="90"> + <position x="438" y="726"/> + <relPosition x="90" y="15"/> + <expression>text</expression> + <pou name="Button" pouType="functionBlock"> + <variable name="back_id"> + <variable name="sele_id"> + <variable name="toggle"> + <variable name="set_state"> + <variable name="state_in"> + <variable name="state_out"> + <variable name="init_Command"> + <derived name="python_eval"/> + <variable name="GetButtonState"> + <derived name="GetBoolString"/> + <variable name="setstate_Command"> + <derived name="python_eval"/> + <variable name="getstate_Command"> + <derived name="python_poll"/> + <variable name="GetButtonToggle"> + <derived name="GetBoolString"/> + <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command"> + <position x="838" y="32"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="50"/> + <connection refLocalId="10"> + <position x="838" y="82"/> + <position x="781" y="82"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="110"/> + <connection refLocalId="2" formalParameter="OUT"> + <position x="838" y="142"/> + <position x="641" y="142"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="50"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="110"/> + <block localId="2" width="150" height="442" typeName="CONCAT"> + <position x="491" y="92"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="50"/> + <connection refLocalId="3"> + <position x="491" y="142"/> + <position x="433" y="142"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="110"/> + <connection refLocalId="11"> + <position x="491" y="202"/> + <position x="431" y="202"/> + <variable formalParameter="IN3"> + <relPosition x="0" y="170"/> + <connection refLocalId="5"> + <position x="491" y="262"/> + <position x="431" y="262"/> + <variable formalParameter="IN4"> + <relPosition x="0" y="230"/> + <connection refLocalId="12"> + <position x="491" y="322"/> + <position x="430" y="322"/> + <variable formalParameter="IN5"> + <relPosition x="0" y="290"/> + <connection refLocalId="23"> + <position x="491" y="382"/> + <position x="463" y="382"/> + <position x="463" y="370"/> + <position x="430" y="370"/> + <variable formalParameter="IN6"> + <relPosition x="0" y="350"/> + <connection refLocalId="24" formalParameter="CODE"> + <position x="491" y="442"/> + <position x="429" y="442"/> + <variable formalParameter="IN7"> + <relPosition x="0" y="410"/> + <connection refLocalId="9"> + <position x="491" y="502"/> + <position x="430" y="502"/> + <variable formalParameter="OUT"> + <relPosition x="150" y="50"/> + <inVariable localId="3" height="30" width="400"> + <position x="33" y="127"/> + <relPosition x="400" y="15"/> + <expression>'createSVGUIControl("button",back_id="'</expression> + <inVariable localId="5" height="30" width="140"> + <position x="291" y="247"/> + <relPosition x="140" y="15"/> + <expression>'",sele_id="'</expression> + <inVariable localId="9" height="30" width="180"> + <position x="250" y="487"/> + <relPosition x="180" y="15"/> + <expression>',active=True)'</expression> + <inVariable localId="10" height="30" width="70"> + <position x="711" y="67"/> + <relPosition x="70" y="15"/> + <expression>BOOL#1</expression> + <inVariable localId="11" height="35" width="85"> + <position x="346" y="187"/> + <relPosition x="85" y="15"/> + <expression>back_id</expression> + <inVariable localId="12" height="35" width="85"> + <position x="345" y="307"/> + <relPosition x="85" y="15"/> + <expression>sele_id</expression> + <inVariable localId="13" height="35" width="100"> + <position x="452" y="639"/> + <relPosition x="100" y="15"/> + <expression>set_state</expression> + <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonState"> + <position x="239" y="897"/> + <variable formalParameter="VALUE"> + <relPosition x="0" y="30"/> + <connection refLocalId="32"> + <position x="239" y="927"/> + <position x="181" y="927"/> + <variable formalParameter="CODE"> + <relPosition x="140" y="30"/> + <outVariable localId="29" height="30" width="53"> + <position x="1015" y="127"/> + <relPosition x="0" y="15"/> + <connection refLocalId="1" formalParameter="RESULT"> + <position x="1015" y="142"/> + <position x="963" y="142"/> + <expression>ID</expression> + <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command"> + <position x="810" y="640"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="50"/> + <connection refLocalId="31" formalParameter="OUT"> + <position x="810" y="690"/> + <position x="762" y="690"/> + <position x="762" y="612"/> + <position x="710" y="612"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="110"/> + <connection refLocalId="7" formalParameter="OUT"> + <position x="810" y="750"/> + <position x="643" y="750"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="50"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="110"/> + <connector name="CREATED" localId="30" height="30" width="110"> + <position x="1014" y="67"/> + <relPosition x="0" y="15"/> + <connection refLocalId="1" formalParameter="ACK"> + <position x="1014" y="82"/> + <position x="963" y="82"/> + <continuation name="CREATED" localId="6" height="30" width="110"> + <position x="442" y="597"/> + <relPosition x="110" y="15"/> + <block localId="31" width="75" height="105" typeName="AND"> + <position x="635" y="571"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="41"/> + <connection refLocalId="6"> + <position x="635" y="612"/> + <position x="552" y="612"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="83"/> + <connection refLocalId="13"> + <position x="635" y="654"/> + <position x="552" y="654"/> + <variable formalParameter="OUT"> + <relPosition x="75" y="41"/> + <inVariable localId="32" height="30" width="90"> + <position x="91" y="912"/> + <relPosition x="90" y="15"/> + <expression>state_in</expression> + <outVariable localId="33" height="30" width="100"> + <position x="1334" y="1184"/> + <relPosition x="0" y="15"/> + <connection refLocalId="26" formalParameter="OUT"> + <position x="1334" y="1199"/> + <position x="1286" y="1199"/> + <expression>state_out</expression> + <block localId="7" width="150" height="319" typeName="CONCAT"> + <position x="493" y="701"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="49"/> + <connection refLocalId="14"> + <position x="493" y="750"/> + <position x="379" y="750"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="108"/> + <connection refLocalId="8"> + <position x="493" y="809"/> + <position x="435" y="809"/> + <position x="435" y="803"/> + <position x="379" y="803"/> + <variable formalParameter="IN3"> + <relPosition x="0" y="167"/> + <connection refLocalId="15"> + <position x="493" y="868"/> + <position x="435" y="868"/> + <position x="435" y="855"/> + <position x="379" y="855"/> + <variable formalParameter="IN4"> + <relPosition x="0" y="226"/> + <connection refLocalId="28" formalParameter="CODE"> + <position x="493" y="927"/> + <position x="379" y="927"/> + <variable formalParameter="IN5"> + <relPosition x="0" y="285"/> + <connection refLocalId="16"> + <position x="493" y="986"/> + <position x="377" y="986"/> + <variable formalParameter="OUT"> + <relPosition x="150" y="49"/> + <inVariable localId="8" height="30" width="53"> + <position x="326" y="788"/> + <relPosition x="53" y="15"/> + <expression>ID</expression> + <inVariable localId="14" height="30" width="120"> + <position x="259" y="735"/> + <relPosition x="120" y="15"/> + <expression>'setAttr('</expression> + <inVariable localId="15" height="30" width="122"> + <position x="257" y="840"/> + <relPosition x="122" y="15"/> + <expression>',"state",'</expression> + <inVariable localId="16" height="30" width="41"> + <position x="336" y="971"/> + <relPosition x="41" y="15"/> + <expression>')'</expression> + <block localId="17" width="125" height="140" typeName="python_poll" instanceName="getstate_Command"> + <position x="801" y="1089"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="50"/> + <connection refLocalId="18"> + <position x="801" y="1139"/> + <position x="763" y="1139"/> + <position x="763" y="1099"/> + <position x="720" y="1099"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="110"/> + <connection refLocalId="22" formalParameter="OUT"> + <position x="801" y="1199"/> + <position x="643" y="1199"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="50"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="110"/> + <block localId="25" width="145" height="45" typeName="STRING_TO_INT"> + <position x="966" y="1169"/> + <variable formalParameter="IN"> + <relPosition x="0" y="30"/> + <connection refLocalId="17" formalParameter="RESULT"> + <position x="966" y="1199"/> + <position x="926" y="1199"/> + <variable formalParameter="OUT"> + <relPosition x="145" y="30"/> + <block localId="26" width="125" height="45" typeName="INT_TO_BOOL"> + <position x="1161" y="1169"/> + <variable formalParameter="IN"> + <relPosition x="0" y="30"/> + <connection refLocalId="25" formalParameter="OUT"> + <position x="1161" y="1199"/> + <position x="1111" y="1199"/> + <variable formalParameter="OUT"> + <relPosition x="125" y="30"/> + <continuation name="CREATED" localId="18" height="30" width="110"> + <position x="610" y="1084"/> + <relPosition x="110" y="15"/> + <inVariable localId="19" height="30" width="53"> + <position x="383" y="1238"/> + <relPosition x="53" y="15"/> + <expression>ID</expression> + <inVariable localId="20" height="30" width="150"> + <position x="286" y="1184"/> + <relPosition x="150" y="15"/> + <expression>'int(getAttr('</expression> + <inVariable localId="21" height="30" width="190"> + <position x="246" y="1292"/> + <relPosition x="190" y="15"/> + <expression>',"state",False))'</expression> + <block localId="22" width="150" height="183" typeName="CONCAT"> + <position x="493" y="1152"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="47"/> + <connection refLocalId="20"> + <position x="493" y="1199"/> + <position x="436" y="1199"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="101"/> + <connection refLocalId="19"> + <position x="493" y="1253"/> + <position x="436" y="1253"/> + <variable formalParameter="IN3"> + <relPosition x="0" y="155"/> + <connection refLocalId="21"> + <position x="493" y="1307"/> + <position x="483" y="1307"/> + <position x="483" y="1307"/> + <position x="436" y="1307"/> + <variable formalParameter="OUT"> + <relPosition x="150" y="47"/> + <inVariable localId="23" height="30" width="130"> + <position x="300" y="355"/> + <relPosition x="130" y="15"/> + <expression>'",toggle='</expression> + <block localId="24" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonToggle"> + <position x="289" y="412"/> + <variable formalParameter="VALUE"> + <relPosition x="0" y="30"/> + <connection refLocalId="27"> + <position x="289" y="442"/> + <position x="220" y="442"/> + <variable formalParameter="CODE"> + <relPosition x="140" y="30"/> + <inVariable localId="27" height="30" width="90"> + <position x="130" y="427"/> + <relPosition x="90" y="15"/> + <expression>toggle</expression> + <pou name="Led" pouType="functionBlock"> + <variable name="back_id"> + <variable name="sele_id"> + <variable name="state_in"> + <variable name="init_Command"> + <derived name="python_eval"/> + <variable name="setstate_Command"> + <derived name="python_poll"/> + <variable name="GetLedState"> + <derived name="GetBoolString"/> + <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command"> + <position x="810" y="30"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="50"/> + <connection refLocalId="10"> + <position x="810" y="80"/> + <position x="753" y="80"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="110"/> + <connection refLocalId="2" formalParameter="OUT"> + <position x="810" y="140"/> + <position x="640" y="140"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="50"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="110"/> + <block localId="2" width="150" height="322" typeName="CONCAT"> + <position x="490" y="90"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="50"/> + <connection refLocalId="3"> + <position x="490" y="140"/> + <position x="415" y="140"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="110"/> + <connection refLocalId="11"> + <position x="490" y="200"/> + <position x="415" y="200"/> + <variable formalParameter="IN3"> + <relPosition x="0" y="170"/> + <connection refLocalId="5"> + <position x="490" y="260"/> + <position x="415" y="260"/> + <variable formalParameter="IN4"> + <relPosition x="0" y="230"/> + <connection refLocalId="12"> + <position x="490" y="320"/> + <position x="414" y="320"/> + <variable formalParameter="IN5"> + <relPosition x="0" y="290"/> + <connection refLocalId="9"> + <position x="490" y="380"/> + <position x="414" y="380"/> + <variable formalParameter="OUT"> + <relPosition x="150" y="50"/> + <inVariable localId="3" height="30" width="400"> + <position x="15" y="125"/> + <relPosition x="400" y="15"/> + <expression>'createSVGUIControl("button",back_id="'</expression> + <block localId="4" width="125" height="140" typeName="python_poll" instanceName="setstate_Command"> + <position x="782" y="536"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="50"/> + <connection refLocalId="6"> + <position x="782" y="586"/> + <position x="653" y="586"/> + <position x="653" y="552"/> + <position x="602" y="552"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="110"/> + <connection refLocalId="7" formalParameter="OUT"> + <position x="782" y="646"/> + <position x="615" y="646"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="50"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="110"/> + <inVariable localId="5" height="30" width="140"> + <position x="275" y="245"/> + <relPosition x="140" y="15"/> + <expression>'",sele_id="'</expression> + <continuation name="CREATED" localId="6" height="30" width="110"> + <position x="492" y="537"/> + <relPosition x="110" y="15"/> + <block localId="7" width="150" height="319" typeName="CONCAT"> + <position x="465" y="597"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="49"/> + <connection refLocalId="14"> + <position x="465" y="646"/> + <position x="351" y="646"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="108"/> + <connection refLocalId="8"> + <position x="465" y="705"/> + <position x="407" y="705"/> + <position x="407" y="699"/> + <position x="351" y="699"/> + <variable formalParameter="IN3"> + <relPosition x="0" y="167"/> + <connection refLocalId="15"> + <position x="465" y="764"/> + <position x="407" y="764"/> + <position x="407" y="751"/> + <position x="351" y="751"/> + <variable formalParameter="IN4"> + <relPosition x="0" y="226"/> + <connection refLocalId="28" formalParameter="CODE"> + <position x="465" y="823"/> + <position x="351" y="823"/> + <variable formalParameter="IN5"> + <relPosition x="0" y="285"/> + <connection refLocalId="16"> + <position x="465" y="882"/> + <position x="407" y="882"/> + <position x="407" y="883"/> + <position x="351" y="883"/> + <variable formalParameter="OUT"> + <relPosition x="150" y="49"/> + <inVariable localId="8" height="30" width="53"> + <position x="298" y="684"/> + <relPosition x="53" y="15"/> + <expression>ID</expression> + <inVariable localId="9" height="30" width="300"> + <position x="124" y="365"/> + <relPosition x="300" y="15"/> + <expression>'",toggle=True,active=False)'</expression> + <inVariable localId="10" height="30" width="70"> + <position x="683" y="65"/> + <relPosition x="70" y="15"/> + <expression>BOOL#1</expression> + <inVariable localId="11" height="35" width="85"> + <position x="330" y="185"/> + <relPosition x="85" y="15"/> + <expression>back_id</expression> + <inVariable localId="12" height="35" width="85"> + <position x="329" y="305"/> + <relPosition x="85" y="15"/> + <expression>sele_id</expression> + <inVariable localId="14" height="30" width="120"> + <position x="231" y="631"/> + <relPosition x="120" y="15"/> + <expression>'setAttr('</expression> + <inVariable localId="15" height="30" width="122"> + <position x="229" y="736"/> + <relPosition x="122" y="15"/> + <expression>',"state",'</expression> + <inVariable localId="16" height="30" width="41"> + <position x="310" y="868"/> + <relPosition x="41" y="15"/> + <expression>')'</expression> + <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetLedState"> + <position x="211" y="793"/> + <variable formalParameter="VALUE"> + <relPosition x="0" y="30"/> + <connection refLocalId="32"> + <position x="211" y="823"/> + <position x="153" y="823"/> + <variable formalParameter="CODE"> + <relPosition x="140" y="30"/> + <outVariable localId="29" height="30" width="53"> + <position x="987" y="125"/> + <relPosition x="0" y="15"/> + <connection refLocalId="1" formalParameter="RESULT"> + <position x="987" y="140"/> + <position x="935" y="140"/> + <expression>ID</expression> + <connector name="CREATED" localId="30" height="30" width="110"> + <position x="986" y="65"/> + <relPosition x="0" y="15"/> + <connection refLocalId="1" formalParameter="ACK"> + <position x="986" y="80"/> + <position x="935" y="80"/> + <inVariable localId="32" height="30" width="90"> + <position x="63" y="808"/> + <relPosition x="90" y="15"/> + <expression>state_in</expression> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/__init__.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,2 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/build.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,724 @@
+from os.path import join, dirname, basename, abspath, split, isfile, isdir +from optparse import OptionParser +from cStringIO import StringIO + from hashlib import md5 + usage: %prog [options] <application module name or path> +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 +# -------------+-----------------------+----------------------+---------------------- +# 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", + p = os.path.join(_data_dir, 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): + names = os.listdir(src) + if name.startswith('CVS'): + if name.startswith('.git'): + if name.startswith('.svn'): + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + if symlinks and os.path.islink(srcname): + linkto = os.readlink(srcname) + os.symlink(linkto, dstname) + copytree_exists(srcname, dstname, symlinks) + shutil.copy2(srcname, dstname) + except (IOError, os.error), why: + errors.append((srcname, dstname, why)) +def check_html_file(source_file, dest_path): + """ Checks if a base HTML-file is available in the PyJamas + 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 + 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] + <!-- auto-generated html - you should consider editing and + adapting this to suit your requirements + <meta name="pygwt:module" content="%(modulename)s"> + <title>%(title)s</title> + <script language="javascript" src="pygwt.js"></script> + 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 ): + os.path.join ( dest_path, mod_name + '.css' ) ) : + css = "<link rel='stylesheet' href='" + mod_name + ".css'>" + os.path.join ( dest_path, 'pyjamas_default.css' ) ) : + css = "<link rel='stylesheet' href='pyjamas_default.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') +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() + msg += " with debugging statements" + # 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 + if not os.path.isdir(output): + print "Creating output directory" + except StandardError, e: + print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e) + pub_dir = join(p, 'public') + 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): + shutil.copy(html_input_filename, html_output_filename) + 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 + 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() + 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) + 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"), + # 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( + 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): + print "Deleting existing app file %s" % p + tmpl = read_boilerplate(data_dir, "all.cache.html") + parser = pyjs.PlatformParser("platform") + scripts = ['<script type="text/javascript" src="%s"></script>'%script \ + for script in js_includes] + app_body = '\n'.join(scripts) + # First, generate all the code. + # Second, (dynamic only), post-analyse the places where modules + # Third, write everything out. + for platform in app_platforms: + mod_code[platform] = {} + mod_libs[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, + library_modules=['dynamicajax.js', + pover[platform].update(app_translator.overrides.items()) + for mname, name in app_translator.overrides.items(): + pd = overrides.setdefault(mname, {}) + #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 + deps = map(pyjs.strip_py, modules_to_do) + sublist = add_subdeps(dependencies, d) + modules_to_do += sublist + #dependencies[app_name] = deps + modules[platform] = modules_done + 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: + 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, + pover[platform].update(mod_translator.overrides.items()) + for mname, name in mod_translator.overrides.items(): + pd = overrides.setdefault(mname, {}) + mods = mod_translator.library_modules + modules[platform] += mods + deps = map(pyjs.strip_py, mods) + while mod_name in deps: + #print "modname preadd:", mod_name, deps + sublist = add_subdeps(dependencies, d) + modules_to_do += sublist + modules_to_do += add_subdeps(dependencies, mod_name) + #print "modname:", mod_name, 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]) + 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) + mod_cache_name = "%s.cache.js" % (mod_name) + print "Creating: " + mod_cache_name + modlevels = make_deps(None, dependencies, dependencies[mod_name]) + 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 = "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) + mod_cache_html_output = open(join(output, mod_cache_name), "w") + mod_cache_html_output = StringIO() + print >>mod_cache_html_output, mod_cache_html_template % dict( + mod_libs = mod_libs[platform][mod_name], + mod_cache_html_output.close() + mod_cache_html_output.seek(0) + app_libs_ += mod_cache_html_output.read() + # write out the dependency ordering of the modules + 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 = "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 + # now write app.allcache including dependency-ordered list of + file_contents = all_cache_html_template % dict( + early_app_libs = early_app_libs_, + platform = platform.lower(), + app_modnames = app_modnames, + app_headers = app_headers + digest = md5.new(file_contents).hexdigest() + file_name = "%s.%s.%s" % (platform.lower(), app_name, digest) + 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) + app_files.append((platform.lower(), file_name)) + print "Created app file %s:%s: %s" % ( + app_name, platform, out_path) +# creates sub-dependencies e.g. pyjamas.ui.Widget +# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas. + for i in range(0, len(m)): + d.append('.'.join(m[:i+1])) +def add_subdeps(deps, mod_name): + #print "subdeps", mod_name, sd + for i in range(0, len(sd)-1): + l = deps.get(child, []) +# makes unique and preserves list order +def filter_mods(app_name, md): + md = filter(lambda x: not x.endswith('.js'), md) + md = map(pyjs.strip_py, md) +def filter_deps(app_name, deps): + for (k, l) in deps.items(): + mods = filter_mods(k, l) +def has_nodeps(mod, deps): + if not deps.has_key(mod) or not deps[mod]: +def nodeps_list(mod_list, deps): + if has_nodeps(mod, deps): +# 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... +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) + for m, dl in deps.items(): + if m in deps.get(d, []): + raise Exception('Circular Imports found: \n%s %s -> %s %s' + #raise Exception('Could not calculate dependencies: \n%s' % 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) + depslist = filter(lambda x: x not in nodeps, depslist) + #print "newdeps", newdeps + ordered_deps.append(nodeps) + ordered_deps.append(mod_list) # last dependencies - usually the app(s) + 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", + 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"), + (options, args) = parser.parse_args() + parser.error("incorrect number of arguments") + data_dir = abspath(options.data_dir) + 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) + for d in options.library_dirs: + pyjs.path.append(abspath(d)) + 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__": --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/jsonrpc/README.txt Tue May 08 17:08:45 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 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,226 @@
+# 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 +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): + if isinstance(service, JSONRPCService): + service.add_method(func.__name__, func) + emsg = 'Service "%s" not found' % str(service.__name__) + raise NotImplementedError, emsg +# 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 +# (r'^formsservice/$', 'djangoapp.views.processor'), +from django import forms + for error in form.errors.keys(): + for errorval in form.errors[error]: + d[error].append(unicode(errorval)) +# contains the list of arguments in each field + '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): + field_type = field.__class__.__name__ + for n, m in field.error_messages.items(): + res['error_messages'] = msgs + if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']: + res['fields'] = map(describe_field, field.fields) +def describe_fields_errors(fields, field_names): + field_names = fields.keys() + for name in field_names: + res[name] = describe_field_errors(field) +def describe_field(field): + 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) +def describe_fields(fields, field_names): + field_names = fields.keys() + for name in field_names: + res[name] = describe_field(field) +class FormProcessor(JSONRPCService): + def __init__(self, forms, _formcls=None): + JSONRPCService.__init__(self) + s = FormProcessor({}, forms[k]) + self.add_method(k, s.__process) + JSONRPCService.__init__(self, forms) + self.formcls = _formcls + def __process(self, request, params, command=None): + f = self.formcls(params) + if command is None: # just validate + 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'): + 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. +# 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 +from datetime import date +def dict_datetimeflatten(item): + for k, v in item.items(): + if isinstance(v, datetime.date): + elif isinstance(v, dict): + d[k] = dict_datetimeflatten(v) +def json_convert(l, fields=None): + for item in serialize('python', l, fields=fields): + res.append(dict_datetimeflatten(item)) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/jsonrpc/jsonrpc.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,43 @@
+import gluon.contrib.simplejson as simplejson +class JSONRPCServiceBase: + 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, + 'error': {'name': 'JSONRPCError', + 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: + result =self.methods[method](*params) + return self.response(id, result) + etype, eval, etb = sys.exc_info() + return self.error(id, 100, '%s: %s' %(etype.__name__, eval)) + etype, eval, etb = sys.exc_info() + return self.error(id, 100, 'Exception %s: %s' %(etype, eval)) + return self.error(id, 100, 'method "%s" does not exist' % method) + return self.methods.keys() --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,11 @@
+from pyjs.jsonrpc import JSONRPCServiceBase +class JSONRPCService(JSONRPCServiceBase): + return self.process(request.body.read()) + def __call__(self,func): + self.methods[func.__name__]=func --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/lib/_pyjs.js Tue May 08 17:08:45 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)) + 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) { + 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 instance = new fn_cls(); + if(instance.__init__) instance.__init__.apply(instance, arguments); + 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() { + for (bi in fn_cls.__baseclasses) + var b = fn_cls.__baseclasses[bi]; + if (b.__was_initialized__) + for (bi in fn_cls.__baseclasses) + var b = fn_cls.__baseclasses[bi]; + pyjs_extend(fn_cls, b); + bases = [pyjslib.__Object]; + fn_cls.__baseclasses = bases; + fn_cls.__initialize__(); + 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; + fn_cls.prototype.__class__[k] = mth; +function pyjs_kwargs_call(obj, func, star_args, args) + if (!pyjslib.isIteratable(star_args)) + throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args))); + var __i = star_args.__iter__(); + call_args[i]=__i.next(); + if (e != pyjslib.StopIteration) { + var n = star_args.length; + for (var i=0; i < args.length; i++) { + call_args[n+i]=args[i]; + 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; --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/lib/json.js Tue May 08 17:08:45 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 + var at, // The index of the current character + ch, // The current character +// Call error when something is wrong. +// If a c parameter is provided, verify that it matches the current character. + error("Expected '" + c + "' instead of '" + ch + "'"); +// Get the next character. When there are no more characters, +// return the empty string. +// Parse a number value. + while (ch >= '0' && ch <= '9') { + while (next() && ch >= '0' && ch <= '9') { + if (ch === 'e' || ch === 'E') { + if (ch === '-' || ch === '+') { + while (ch >= '0' && ch <= '9') { +// Parse a string value. +// When parsing for string values, we must look for " and \ characters. + } else if (ch === '\\') { + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + uffff = uffff * 16 + hex; + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + while (ch && ch <= ' ') { +// true, false, or null. + error("Unexpected '" + ch + "'"); + value, // Place holder for the value function. +// Parse an array value. + return array; // empty array +// Parse an object value. + return object; // empty object + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); +// Parse a JSON value. It could be an object, an array, a string, a number, + 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) { +// 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 + return typeof reviver === 'function' ? (function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + if (Object.hasOwnProperty.call(value, k)) { + return reviver.call(holder, key, value); + }({'': result}, '')) : result; --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/lib/pyjslib.py Tue May 08 17:08:45 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): + if (module_name == "sys" || module_name == 'pyjslib') + /*module_load_request[module_name] = 1;*/ + var override_name = sys.platform + "." + module_name; + if (((sys.overrides != null) && + (sys.overrides.has_key(override_name)))) + cache_file = sys.overrides.__getitem__(override_name) ; + cache_file = module_name ; + cache_file = (path + cache_file + '.cache.js' ) ; + //alert("cache " + cache_file + " " + module_name + " " + parent_module); + 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 */ + 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 + 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+');';*/ + /* 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);*/ + if (module_name != "pyjslib" && +function import_wait(proceed_fn, parent_mod, dynamic) { + var element = $doc.createElement("div"); + $doc.body.appendChild(element); + function write_dom(txt) { + element.innerHTML = txt + '<br />'; + var wait = function() { + for (l in module_load_request) + var m = module_load_request[l]; + if (l == "sys" || l == 'pyjslib') + //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod); + setTimeout(wait, timeoutperiod); + for (l in module_load_request) + var m = module_load_request[l]; + if (l == "sys" || l == 'pyjslib') + module_load_request[l] = 4; + if ((parent_mod != null) && (l == parent_mod)) + setTimeout(wait, timeoutperiod); + /* cheat and move app on to next stage */ + module_load_request[l] = 3; + setTimeout(wait, timeoutperiod); + //alert("waited for module " + l + ": loaded"); + module_load_request[l] = 4; + //alert("module wait done"); + if (proceed_fn.importDone) + proceed_fn.importDone(proceed_fn); + def __init__(self, path, app_modlist, app_imported_fn, dynamic, + self.app_modlist = app_modlist + self.app_imported_fn = app_imported_fn + self.parent_mod = parent_mod + 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); + if self.idx >= len(self.app_modlist): + import_wait(self.app_imported_fn, self.parent_mod, self.dynamic) + import_wait(getattr(self, "next"), self.parent_mod, self.dynamic) +def get_module(module_name): + ev = "__mod = %s;" % module_name +def preload_app_modules(path, app_modnames, app_imported_fn, dynamic, + loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod) + def __init__(self, *args): + if len(self.args) is 0: + elif len(self.args) is 1: + return repr(self.args[0]) +class Exception(BaseException): +class TypeError(BaseException): +class StandardError(Exception): +class LookupError(StandardError): + return self.name + ": " + self.args[0] +class KeyError(LookupError): +class AttributeError(StandardError): + name = "AttributeError" + return "AttributeError: %s of %s" % (self.args[1], self.args[0]) +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; +pyjslib.String_join = function(data) { + if (pyjslib.isArray(data)) { + return data.join(this); + else if (pyjslib.isIteratable(data)) { + var iter=data.__iter__(); + if (e != pyjslib.StopIteration) throw e; +pyjslib.String_isdigit = function() { + return (this.match(/^\d+$/g) != null); +pyjslib.String_replace = function(old, replace, count) { + if (!pyjslib.isString(old)) return this.__replace(old, replace); + if (!pyjslib.isUndefined(count)) do_max=true; + while (start<this.length) { + if (do_max && !count--) break; + pos=this.indexOf(old, start); + new_str+=this.substring(start, pos) + replace; + if (start<this.length) new_str+=this.substring(start); +pyjslib.String_split = function(sep, maxsplit) { + var items=new pyjslib.List(); + if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) { + subject=subject.strip(); + subject=subject.replace(/\s+/g, sep); + else if (!pyjslib.isUndefined(maxsplit)) do_max=true; + if (subject.length == 0) { + while (start<subject.length) { + if (do_max && !maxsplit--) break; + pos=subject.indexOf(sep, start); + items.append(subject.substring(start, pos)); + if (start<=subject.length) items.append(subject.substring(start)); +pyjslib.String___iter__ = function() { + throw pyjslib.StopIteration; + return s.substring(i++, i, 1); + '__iter__': function() { +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; + def __init__(self, name): + if (pyjslib.hasattr(a, "__cmp__")) { + return a.__cmp__(b) == 0; + } else if (pyjslib.hasattr(b, "__cmp__")) { + return b.__cmp__(a) == 0; + if hasattr(a, "__cmp__"): + elif hasattr(b, "__cmp__"): + # this needs to stay in native code without any dependencies here, + # because this is used by if and while, we need to prevent + return v.__nonzero__(); + def __init__(self, data=None): + def append(self, item): + JS(""" this.l[this.l.length] = item;""") + def extend(self, data): + if (pyjslib.isArray(data)) { + for (var i=0; i < data.length; i++) { + else if (pyjslib.isIteratable(data)) { + var iter=data.__iter__(); + if (e != pyjslib.StopIteration) throw e; + def remove(self, value): + var index=this.index(value); + if (index<0) return false; + this.l.splice(index, 1); + def index(self, value, start=0): + var length=this.l.length; + for (var i=start; i<length; i++) { + if (this.l[i]==value) { + def insert(self, index, value): + JS(""" var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""") + def pop(self, index = -1): + if (index<0) index = this.l.length + index; + this.l.splice(index, 1); + if not isinstance(l, List): + ll = len(self) - len(l) + for x in range(len(l)): + ll = cmp(self.__getitem__(x), l[x]) + def slice(self, lower, upper): + if (upper==null) return pyjslib.List(this.l.slice(lower)); + return pyjslib.List(this.l.slice(lower, upper)); + def __getitem__(self, index): + if (index<0) index = this.l.length + index; + def __setitem__(self, index, value): + JS(""" this.l[index]=value;""") + def __delitem__(self, index): + JS(""" this.l.splice(index, 1);""") + JS(""" return this.l.length;""") + def __contains__(self, value): + return self.index(value) >= 0 + throw pyjslib.StopIteration; + '__iter__': function() { + JS(""" this.l.reverse();""") + def sort(self, compareFunc=None, keyFunc=None, reverse=False): + if keyFunc and reverse: + return -compareFunc(keyFunc(a), keyFunc(b)) + return compareFunc(keyFunc(a), keyFunc(b)) + return -compareFunc(a, b) + self.l.sort(compareFunc) + Access the javascript Array that is used internally by this list + def __init__(self, data=None): + def append(self, item): + JS(""" this.l[this.l.length] = item;""") + def extend(self, data): + if (pyjslib.isArray(data)) { + for (var i=0; i < data.length; i++) { + else if (pyjslib.isIteratable(data)) { + var iter=data.__iter__(); + if (e != pyjslib.StopIteration) throw e; + def remove(self, value): + var index=this.index(value); + if (index<0) return false; + this.l.splice(index, 1); + def index(self, value, start=0): + var length=this.l.length; + for (var i=start; i<length; i++) { + if (this.l[i]==value) { + def insert(self, index, value): + JS(""" var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""") + def pop(self, index = -1): + if (index<0) index = this.l.length + index; + this.l.splice(index, 1); + if not isinstance(l, Tuple): + ll = len(self) - len(l) + for x in range(len(l)): + ll = cmp(self.__getitem__(x), l[x]) + def slice(self, lower, upper): + if (upper==null) return pyjslib.Tuple(this.l.slice(lower)); + return pyjslib.Tuple(this.l.slice(lower, upper)); + def __getitem__(self, index): + if (index<0) index = this.l.length + index; + def __setitem__(self, index, value): + JS(""" this.l[index]=value;""") + def __delitem__(self, index): + JS(""" this.l.splice(index, 1);""") + JS(""" return this.l.length;""") + def __contains__(self, value): + return self.index(value) >= 0 + throw pyjslib.StopIteration; + '__iter__': function() { + JS(""" this.l.reverse();""") + def sort(self, compareFunc=None, keyFunc=None, reverse=False): + if keyFunc and reverse: + return -compareFunc(keyFunc(a), keyFunc(b)) + return compareFunc(keyFunc(a), keyFunc(b)) + return -compareFunc(a, b) + self.l.sort(compareFunc) + Access the javascript Array that is used internally by this list + def __init__(self, data=None): + if (pyjslib.isArray(data)) { + 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__(); + this.__setitem__(item.__getitem__(0), item.__getitem__(1)); + 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): + var sKey = pyjslib.hash(key); + this.d[sKey]=[key, value]; + def __getitem__(self, key): + var sKey = pyjslib.hash(key); + var value=this.d[sKey]; + if (pyjslib.isUndefined(value)){ + throw pyjslib.KeyError(key); + for (var i in this.d) size++; + def has_key(self, key): + return self.__contains__(key) + def __delitem__(self, key): + var sKey = pyjslib.hash(key); + def __contains__(self, key): + var sKey = pyjslib.hash(key); + return (pyjslib.isUndefined(this.d[sKey])) ? false : true; + var keys=new pyjslib.List(); + for (var key in this.d) { + keys.append(this.d[key][0]); + var values=new pyjslib.List(); + for (var key in this.d) values.append(this.d[key][1]); + var items = new pyjslib.List(); + for (var key in this.d) { + items.append(new pyjslib.List(kv)) + return self.keys().__iter__() + return self.values().__iter__(); + 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): + for k,v in d.iteritems(): + Return the javascript Object which this class uses to store + dictionary keys and values + return Dict(self.items()) +# taken from mochikit: range( [start,] stop[, step] ) + if (arguments.length == 2) { + else if (arguments.length == 3) { + else if (arguments.length>0) stop = arguments[0]; + if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration; + '__iter__': function() { +def slice(object, lower, upper): + if (pyjslib.isString(object)) { + lower = object.length + lower; + 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); + if (pyjslib.hasattr(text,"__str__")) { + if(isString(x) and len(x) is 1): + return x.charCodeAt(0); + throw pyjslib.TypeError(); + return String.fromCharCode(x) + return t == 'boolean' || +def get_pyjs_classtype(x): + if (pyjslib.hasattr(x, "__class__")) + if (pyjslib.hasattr(x.__class__, "__new__")) + var src = x.__class__.__name__; + """ Return the string representation of 'x'. + //alert("repr typeof " + t + " : " + x); + return "<function " + x.toString() + ">"; + if (x.indexOf("'") == -1) + if (x.indexOf('"') == -1) + var s = x.replace(new RegExp('"', "g"), '\\\\"'); + // 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(); + for (var i=0; i < contents.length; i++) { + s += pyjslib.repr(contents[i]); + if (i < contents.length - 1) + if (constructor == "List") { + var contents = x.getArray(); + for (var i=0; i < contents.length; i++) { + s += pyjslib.repr(contents[i]); + if (i < contents.length - 1) + if (constructor == "Dict") { + var keys = new Array(); + for (var i=0; i<keys.length; i++) { + s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]); + // If we get here, the class isn't one we know -> 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>"; + return parseFloat(text); + return parseInt(text, radix); + if (object==null) return 0; + if (pyjslib.isObject(object) && object.__len__) return object.__len__(); +def isinstance(object_, classinfo): + if pyjslib.isUndefined(object_): + if not pyjslib.isObject(object_): + if _isinstance(classinfo, Tuple): + if isinstance(object_, ci): + return _isinstance(object_, classinfo) +def _isinstance(object_, classinfo): + if not pyjslib.isObject(object_): + if (object_.__class__){ + var res = object_ instanceof classinfo.constructor; +def getattr(obj, name, default_): + if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){ + if (pyjslib.isUndefined(default_)){ + throw pyjslib.AttributeError(obj, name); + if (!pyjslib.isFunction(obj[name])) return obj[name]; + var fnwrap = function() { + for (var i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + return obj[name].apply(obj,args); + fnwrap.__name__ = name; +def setattr(obj, name, value): + if (!pyjslib.isObject(obj)) return null; + if (!pyjslib.isObject(obj)) return false; + if (pyjslib.isUndefined(obj[name])) return false; + var properties=new pyjslib.List(); + for (property in obj) properties.append(property); +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 + if method.call(obj, item): +def map(obj, method, sequence=None): + items.append(method(item)) + items.append(method.call(obj, item)) +def enumerate(sequence): + enumeration.append([nextIndex, item]) + nextIndex = nextIndex + 1 + 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; +# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html + return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a); + return typeof a == 'function'; + return typeof a == 'string'; + return typeof a == 'object' && !a; + return pyjslib.isObject(a) && a.constructor == Array; + return typeof a == 'undefined'; + return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__); + return typeof a == 'number' && isFinite(a); + Convert the pyjs pythonic List and Dict objects into javascript Object and Array + for(var k=0; k < x.length; k++) { + var tv = pyjslib.toJSObjects(v); + if isinstance(x, Dict): + 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 + var tv = pyjslib.toJSObjects(v) + if ($wnd.console==undefined) return; + for(var i=0; i < objs.length; i++) { +def type(clsname, bases=None, methods=None): + """ creates a class, derived from bases, with methods and variables + for k in methods.keys(): + JS(" var bss = null; ") + JS(" return pyjs_type(clsname, bss, mths); ") --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/lib/sys.py Tue May 08 17:08:45 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 +def addoverride(module_name, path): + overrides[module_name] = path +def addstack(linedebug): + if (pyjslib.bool((sys.stacktrace === null))) { + sys.stacktrace = new pyjslib.List([]); + sys.stacktrace.append(linedebug); + var __l = sys.stacktrace.__iter__(); + if (e != pyjslib.StopIteration) { --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/pyjs/pyjs.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1777 @@
+# 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. +from types import StringType +from compiler import ast +# 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. +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): +# this is the python function used to wrap native javascript +NATIVE_JS_FUNC_NAME = "JS" +PYJSLIB_BUILTIN_FUNCTIONS=("cmp", +PYJSLIB_BUILTIN_CLASSES=("BaseException", +def pyjs_builtin_remap(name): +# XXX: this is a hack: these should be dealt with another way +# however, console is currently the only global name which is causing +PYJS_GLOBAL_VARS=("console") +# This is taken from the django project. +# Escape every ASCII character with a value less than 32. + ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)]) + """Hex encodes characters for use in JavaScript strings.""" + for bad, good in JS_ESCAPES: + value = value.replace(bad, good) +def uuprefix(name, leave_alone=0): + name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:]) + def __init__(self, name, name_): + self.klasses[name] = self + 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 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(".") + 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); + pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false); + """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \ + mod_var_name_decl(importName) + def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output, + dynamic=0, optimize=False, + self.module_prefix = module_name + "." + 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.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.imported_classes = {} + self.method_imported_globals = set() + self.method_self = None + self.nextTupleAssignID = 1 + self.optimize = optimize + self.findFile = findFile + if module_name.find(".") >= 0: + 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) + print >>self.output, decl + 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, """ + var suffix="HaltException"; + if (s.length < suffix.length) { + //alert(s + " " + suffix); + var ss = s.substring(s.length, (s.length - suffix.length)); + //alert(s + " " + suffix + " " + ss); + if isinstance(child, ast.Function): + self.top_level_functions.add(child.name) + elif isinstance(child, ast.Class): + self.top_level_classes.add(child.name) + if isinstance(child, ast.Function): + self._function(child, False) + elif isinstance(child, ast.Class): + 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 + elif importName.endswith('.js'): + self.imported_js.add(importName) + 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 + self.add_imported_module(child.modname) + 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): + elif isinstance(child, ast.For): + 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) + 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: + self.imported_modules.append(importName) + name = importName.split(".") + # 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! + self.imported_modules_as.append(child_name) + print >> self.output, gen_mod_import(self.raw_module_name, + def _default_args_handler(self, node, arg_names, current_klass, + output = output or self.output + default_pos = len(arg_names) - len(node.defaults) + if arg_names and arg_names[0] == self.method_self: + 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) + raise TranslationError("unsupported type (in _method)", default_node) + default_name = arg_names[default_pos] + 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: + 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) +# 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) + #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), "]"])+";" + 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): + function_name = node.name + self.add_local_arg(function_name) + 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 + 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 + 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" + call_name = v.node.name + 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) + elif isinstance(v.node.expr, ast.Getattr): + call_name = self._getattr2(v.node.expr, current_klass, attr_name) + elif isinstance(v.node.expr, ast.CallFunc): + call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname + elif isinstance(v.node.expr, ast.Subscript): + call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname + elif isinstance(v.node.expr, ast.Const): + call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname + raise TranslationError("unsupported type (in _callfunc)", v.node.expr) + raise TranslationError("unsupported type (in _callfunc)", v.node) + call_name = strip_py(call_name) + star_arg_name = self.expr(v.star_args, current_klass) + if isinstance(ch4, ast.Keyword): + kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass) + arg = self.expr(ch4, current_klass) + fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args) + fn_args = ", ".join(call_args) + if kwargs or star_arg_name: + try: call_this, method_name = call_name.rsplit(".", 1) + # Must be a function call ... + return ("pyjs_kwargs_function_call("+call_name+", " + return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', " + return call_name + "(" + ", ".join(call_args) + ")" + def _print(self, node, current_klass): + arg = self.expr(ch4, current_klass) + 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] + # 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 isinstance(expr, ast.Tuple): + l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass))) + 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) + #print >> self.output, "} else { throw(%s); } " % errName + print >> self.output, "}" + 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): + 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 + raise TranslationError("unsupported type (in _getattr)", v.expr) + 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 + las = len(self.local_arg_stack) + local_var_names = self.local_arg_stack[-1] + elif v.name == "False": + elif v.name == '__name__' and current_klass is None: + return self.modpfx() + v.name + elif v.name == self.method_self: + 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: + 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: + elif v.name in PYJSLIB_BUILTIN_CLASSES: + return "pyjslib." + pyjs_builtin_remap( v.name ) + 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 + cls_name_ = current_klass + "_" # XXX ??? + name = UU+cls_name_ + ".prototype.__class__." \ + if v.name == 'listener': + name = 'listener+' + name + def _name2(self, v, current_klass, attr_name): + if obj in self.method_imported_globals: + call_name = UU+self.modpfx() + obj + "." + attr_name + elif self.imported_classes.has_key(obj): + #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 + call_name = UU+self._name(v, current_klass) + "." + attr_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 + obj = self.expr(v.expr, current_klass) + call_name = obj + "." + v.attrname + "." + attr_name + def _class(self, node): + Handle a class definition. + In order to translate python semantics reasonably well, the following + 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_) + for child in node.code: + if isinstance(child, ast.Function): + current_klass.add_function(child.name) + if child.name == "__init__": + 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 + 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 + raise TranslationError("unsupported type (in _class)", node.bases[0]) + current_klass.set_base(base_class) + raise TranslationError("more than one base (in _class)", node) + print >>self.output, UU+class_name_ + " = function () {" + # call superconstructor + # print >>self.output, " __" + base_class + ".call(this);" + print >>self.output, "}" + 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([], + init_method.argnames[1:], + [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" + + 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+" = {};" + 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_+");" + 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): + 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 + 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): + raise TranslationError("More than one expression unsupported", + 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) + for d in node.decorators: + if d.name == "classmethod": + elif d.name == "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;"; + 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) + ")" + fexpr = UU + class_name_ + ".prototype.__class__." + node.name + fexpr = UU + class_name_ + ".prototype." + node.name + print >>self.output, " "+fexpr + " = function" + function_args + " {" + self._default_args_handler(node, normal_arg_names, current_klass) + local_arg_names = normal_arg_names + declared_arg_names + 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) + # Have to create a version on the instances which automatically passes the + 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;" + # 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';" % \ + 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: + def _stmt(self, node, current_klass): + debugStmt = self.debug and not self._isNativeFunc(node) + 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): + 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) + raise TranslationError("unsupported type (in _stmt)", node) + 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 " \ + + '+"\\n"+__err.name+": "+__err.message'\ + + '+"\\n\\nStack trace:\\n"' \ + 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): + if hasattr(node, "lineno"): + if node.lineno != None: + 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 " \ + def _augassign(self, node, current_klass): + 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) + lhs = self._name(node.node, current_klass) + 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) + tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno) + self._assign(tnode2, current_klass, top_level) + if len(self.local_arg_stack) > 0: + local_var_names = self.local_arg_stack[-1] + def _lhsFromAttr(v, current_klass): + if isinstance(v.expr, ast.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 + raise TranslationError("unsupported type (in _assign)", v.expr) + def _lhsFromName(v, top_level, current_klass): + lhs = UU+current_klass.name_ + ".prototype.__class__." \ + 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: + self.add_local_arg(v.name) + if v.name in local_var_names: + elif v.name in self.method_imported_globals: + lhs = self.modpfx() + v.name + self.add_local_arg(v.name) + if isinstance(v, ast.AssAttr): + lhs = _lhsFromAttr(v, current_klass) + if v.flags == "OP_ASSIGN": + raise TranslationError("unsupported flag (in _assign)", v) + elif isinstance(v, ast.AssName): + lhs = _lhsFromName(v, top_level, current_klass) + if v.flags == "OP_ASSIGN": + raise TranslationError("unsupported flag (in _assign)", v) + elif isinstance(v, ast.Subscript): + if v.flags == "OP_ASSIGN": + obj = self.expr(v.expr, current_klass) + 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 + ");" + 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 " + + idx = self.expr(child.subs[0], current_klass) + value = self.expr(node.expr, current_klass) + print >>self.output, " " + obj + ".__setitem__(" \ + + idx + ", " + rhs + ");" + print >>self.output, " " + lhs + " = " + rhs + ";" + raise TranslationError("unsupported type (in _assign)", v) + rhs = self.expr(node.expr, current_klass) + 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': + 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 + expr = self._callfunc(node.expr, current_klass) + print >>self.output, " " + expr + ";" + 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) + 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] + self._if_test(keyword, test, consequence, current_klass) + consequence = node.else_ + self._if_test(keyword, test, consequence, current_klass) + def _if_test(self, keyword, test, consequence, current_klass): + expr = self.expr(test, current_klass) + print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {" + print >>self.output, " " + keyword + " {" + if isinstance(consequence, ast.Stmt): + for child in consequence.nodes: + self._stmt(child, current_klass) + raise TranslationError("unsupported type (in _if_test)", consequence) + print >>self.output, " }" + for name in node.names: + # look up "hack" in AppTranslator as to how findFile gets here + module_name = node.modname + "." + name[0] + ff = self.findFile(module_name + ".py") + self.add_imported_module(module_name) + self.imported_classes[name[0]] = node.modname + def _compare(self, node, current_klass): + lhs = self.expr(node.expr, current_klass) + raise TranslationError("only one ops supported (in _compare)", node) + rhs_node = node.ops[0][1] + rhs = self.expr(rhs_node, current_klass) + return "pyjslib.eq(%s, %s)" % (lhs, rhs) + return rhs + ".__contains__(" + lhs + ")" + return "!" + rhs + ".__contains__(" + lhs + ")" + 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]))+')' + def _and(self, node, current_klass): + expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")" + def _for(self, node, current_klass): + # 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": + elif isinstance(node.assign, ast.AssTuple): + for child in node.assign: + child_name = child.name + assign_name = "temp_" + child_name + self.add_local_arg(child_name) + var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i); + 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) + 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__(); + %(lhs)s %(op)s %(iterator_name)s.next(); + for node in node.body.nodes: + self._stmt(node, current_klass) + print >>self.output, """ + if (e.__name__ != pyjslib.StopIteration.__name__) { + 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) + raise TranslationError("unsupported type (in _while)", node.body) + print >>self.output, " }" + def _const(self, node): + if isinstance(node.value, int): + elif isinstance(node.value, float): + elif isinstance(node.value, basestring): + if isinstance(node.value, unicode): + return "String('%s')" % escapejs(v) + elif node.value is None: + 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) + ")" + raise TranslationError("must have one sub (in _subscript)", node) + 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) + ");" + 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): + 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): + raise TranslationError("varargs are not supported in Lambdas", node) + 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, + print >> res, 'return %s;}' % expr + def _slice(self, node, current_klass): + if node.flags == "OP_APPLY": + lower = self.expr(node.lower, current_klass) + upper = self.expr(node.upper, current_klass) + return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")" + 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) + raise TranslationError("unsupported type (in expr)", node) +def translate(file_name, module_name, debug=False): + f = file(file_name, "r") + output = cStringIO.StringIO() + mod = compiler.parseFile(file_name) + t = Translator(module_name, module_name, module_name, src, debug, mod, output) + return output.getvalue() + def __init__(self, platform_dir = "", verbose=True): + self.platform_dir = platform_dir + def setPlatform(self, platform): + self.platform = platform + def parseModule(self, module_name, file_name): + if not self.parse_cache.has_key(file_name): + mod = compiler.parseFile(file_name) + self.parse_cache[file_name] = mod + mod = self.parse_cache[file_name] + 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) + print "Importing %s (Platform %s)" % (module_name, self.platform) + print "Importing %s" % (module_name) + 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) + 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) + raise TranslationError("function not found: " + function_name, function_node) + def replaceClassMethods(self, tree, class_name, class_node): + # find class to replace + for child in tree.node: + if isinstance(child, ast.Class) and child.name == class_name: + raise TranslationError("class not found: " + class_name, class_node) + for function_node in class_node.code: + if isinstance(function_node, ast.Function): + for child in old_class_node.code: + if isinstance(child, ast.Function) and child.name == function_node.name: + self.copyFunction(child, function_node) + 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 + path, ext = os.path.splitext(fname) + return path.replace(".", "/") + ext + def __init__(self, library_dirs=[], parser=None, dynamic=False, + optimize=False, verbose=True): + self.optimize = optimize + self.library_modules = [] + self.library_dirs = path + library_dirs + self.parser = PlatformParser() + self.parser.dynamic = dynamic + def findFile(self, file_name): + if os.path.isfile(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): + 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): + raise Exception("file not found: " + file_name) + def _translate(self, module_name, is_app=True, debug=False, + 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") + mod, override = self.parser.parseModule(module_name, file_name) + override_name = "%s.%s" % (self.parser.platform.lower(), + self.overrides[override_name] = override_name + t = Translator(mn, module_name, module_name, + src, debug, mod, output, self.dynamic, self.optimize, + 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, + app_code = cStringIO.StringIO() + lib_code = cStringIO.StringIO() + self.library_modules = [] + for library in library_modules: + if library.endswith(".js"): + imported_js.add(library) + self.library_modules.append(library) + 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' + print >> app_code, self._translate( + module_name, is_app, debug=debug, imported_js=imported_js) + path = self.findFile(js) + if os.path.isfile(path): + 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' + print >>sys.stderr, 'Warning: Unable to find imported javascript:', js + return lib_code.getvalue(), app_code.getvalue() + usage: %s file_name [module_name] + print >> sys.stderr, usage % sys.argv[0] + file_name = os.path.abspath(sys.argv[1]) + if not os.path.isfile(file_name): + print >> sys.stderr, "File not found %s" % file_name + module_name = sys.argv[2] + print translate(file_name, module_name), +if __name__ == "__main__": --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/svgui.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,112 @@
+from ConfigTree import opjimg +from py_ext import PythonCodeTemplate +from pyjs import translate + {"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) + # 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)) + 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()) + 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"}) +def _runtime_%(location)s_begin(): + website.LoadHMI(%(svgui_class)s, %(jsmodules)s) +def _runtime_%(location)s_cleanup(): +""" % {"location": location_str, + "svgui_class": "SVGUI_HMI", + "jsmodules" : str(jsmodules), + res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),) + 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()) + self.GetCTRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath) + def _StartInkscape(self): + svgfile = self._getSVGpath() + if not self.GetCTRoot().CheckProjectPathPerm(): + dialog = wx.MessageDialog(self.GetCTRoot().AppFrame, + _("You don't have write permissions.\nOpen Inkscape anyway ?"), + wx.YES_NO|wx.ICON_QUESTION) + open_inkscape = dialog.ShowModal() == wx.ID_YES + if not os.path.isfile(svgfile): --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/svgui_server.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,130 @@
+from nevow import rend, appserver, inevow, tags, loaders, athena +import simplejson as json + def __init__(self, classname, id, **kwargs): + self.classname = classname + self.attrs = kwargs.copy() + 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.RefreshInterface() + def updateoutputs(self, **kwargs): + for attrname, value in kwargs.iteritems(): + if self.outputs.get(attrname) != value: + self.outputs[attrname] = value + self.RefreshInterface() + def RefreshInterface(self): + interface = website.getHMI() + if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit: + d = interface.sendData(self) + d.addCallback(self.InterfaceRefreshed) + def InterfaceRefreshed(self, result): + 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, + 'kwargs': json.dumps(attrs), +def get_object_current_state(obj): + # Convert objects to a dictionary of their representation + d = { '__class__': obj.classname, + 'kwargs': json.dumps(obj.outputs), +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): + 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): + return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii')) + def setattr(self, id, attrname, value): + svguiWidgets[id].setinput(attrname, value) +def createSVGUIControl(*args, **kwargs): + gad = SvguiWidget(args[0], id, **kwargs) + 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) +def setAttr(id, attrname, value): + gad = svguiWidgets.get(id, None) + gad.setoutput(attrname, value) +def updateAttr(id, **kwargs): + gad = svguiWidgets.get(id, None) + gad.updateoutput(**kwargs) +def getAttr(id, attrname, default=None): + gad = svguiWidgets.get(id, None) + return gad.getinput(attrname, default) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/svgui/svguilib.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,117 @@
+ def __init__(self, parent, id, args): + 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 + self.up = not self.state + # Add event on each element of the button + 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) + # method to display the current state of interface + def updateElements(self): + self.sele_elt.setAttribute("display", "none") + self.back_elt.removeAttribute("display") + 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) + def handleEvent(self, evt): + # Quand le bouton de la souris est presse + if evt.type == "mousedown": + updateAttr(self.id, 'state', self.state) + if isCurrentObject(self) and self.dragging: + # Quand le bouton est survole + if evt.type == "mouseover" and self.toggle: + # Quand le curseur quitte la zone du bouton + elif evt.type == "mouseout" and self.toggle: + self.up = not self.state + # Quand le bouton de la souris est relache + elif evt.type == "mouseup": + if self.toggle and self.up == self.state: + self.state = not self.state + updateAttr(self.id, 'state', self.state) + updateAttr(self.id, 'state', self.state) + def __init__(self, parent, id, args): + self.back_elt = getSVGElementById(args.back_id) + if args.text != undefined: + def updateValues(self, values): + if values.text != self.value: + self.text = values.text + updateAttr(self.id, 'text', self.text) + def updateElements(self): + self.back_elt.firstChild.firstChild.textContent = self.text + def handleEvent(self, evt): \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/wxglade_hmi/README Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/wxglade_hmi/__init__.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+from wxglade_hmi import * --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/modules/wxglade_hmi/wxglade_hmi.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,124 @@
+from xml.dom import minidom +from ConfigTree import opjimg +from py_ext import PythonCodeTemplate +class RootClass(PythonCodeTemplate): + {"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__': + 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') + wxgfile_path=self._getWXGLADEpath() + if os.path.exists(wxgfile_path): + wxgfile = open(wxgfile_path, 'r') + wxgtree = minidom.parse(wxgfile) + 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 + 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()) + runtimefile.write(self.GetPythonCode()) +def _runtime_%(location)s_begin(): + wx.MessageBox(_("Please stop PLC to close")) +def _runtime_%(location)s_cleanup(): +""" % {"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": x[0], "class": x[1]}, + "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))}) + return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb")) + def _editWXGLADE(self): + wxg_filename = self._getWXGLADEpath() + if not self.GetCTRoot().CheckProjectPathPerm(): + dialog = wx.MessageDialog(self.GetCTRoot().AppFrame, + _("You don't have write permissions.\nOpen wxGlade anyway ?"), + wx.YES_NO|wx.ICON_QUESTION) + open_wxglade = dialog.ShowModal() == wx.ID_YES + if not os.path.exists(wxg_filename): + hmi_name = self.BaseParams.getName() + open(wxg_filename,"w").write("""<?xml version="1.0"?> + <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0"> + <object class="%(class)s" name="%(name)s" base="EditFrame"> + <style>wxDEFAULT_FRAME_STYLE</style> + """ % {"name": hmi_name, "class": "Class_%s" % hmi_name}) + if wx.Platform == '__WXMSW__': + wxg_filename = "\"%s\""%wxg_filename + self.launch_wxglade([wxg_filename]) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/plc_python.c Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,216 @@
+ * Python Asynchronous execution code + * PLC put python commands in a fifo, respecting execution order + * with the help of C pragmas inserted in python_eval FB code + * Buffer content is read asynchronously, (from non real time part), + * commands are executed and result stored for later use by PLC. + * In this implementation, fifo is a list of pointer to python_eval + * function blocks structures. Some local variables have been added in + * python_eval interface. We use those local variables as buffer and state +#include "iec_types_all.h" +/* The fifo (fixed size, as number of FB is fixed) */ +static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d]; +/* Producer and consumer cursors */ +static int Current_PLC_EvalFB; +static int Current_Python_EvalFB; +/* A global IEC-Python gateway state, for use inside python_eval FBs*/ +#define PYTHON_LOCKED_BY_PYTHON 0 +#define PYTHON_LOCKED_BY_PLC 1 +#define PYTHON_MUSTWAKEUP 2 +#define PYTHON_FINISHED 4 +/* Each python_eval FunctionBlock have it own state */ +#define PYTHON_FB_FREE 0 +#define PYTHON_FB_REQUESTED 1 +#define PYTHON_FB_PROCESSING 2 +#define PYTHON_FB_ANSWERED 3 +int WaitPythonCommands(void); +void UnBlockPythonCommands(void); +int TryLockPython(void); +void UnLockPython(void); +int __init_%(location)s() + /* Initialize cursors */ + Current_Python_EvalFB = 0; + Current_PLC_EvalFB = 0; + PythonState = PYTHON_LOCKED_BY_PYTHON; + for(i = 0; i < %(python_eval_fb_count)d; i++) +void __cleanup_%(location)s() + PythonState = PYTHON_FINISHED; + UnBlockPythonCommands(); +void __retrieve_%(location)s() + /* Check Python thread is not being + * modifying internal python_eval data */ + PythonState = TryLockPython() ? + PYTHON_LOCKED_BY_PYTHON; + /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON + * and python_eval will no do anything */ +void __publish_%(location)s() + if(PythonState & PYTHON_LOCKED_BY_PLC){ + /* If runnig PLC did push something in the fifo*/ + if(PythonState & PYTHON_MUSTWAKEUP){ + /* WakeUp python thread */ + UnBlockPythonCommands(); + * Called by the PLC, each time a python_eval + * FB instance is executed +void __PythonEvalFB(int poll, PYTHON_EVAL* data__) + /* detect rising edge on TRIG to trigger evaluation */ + if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) || + /* polling is equivalent to trig on value rather than on rising edge*/ + (poll && __GET_VAR(data__->TRIG) )) && + /* trig only if not already trigged */ + __GET_VAR(data__->TRIGGED) == 0){ + __SET_VAR(data__->, TRIGGED, 1); + /* make a safe copy of the code */ + __SET_VAR(data__->, PREBUFFER, __GET_VAR(data__->CODE)); + /* retain value for next rising edge detection */ + __SET_VAR(data__->, TRIGM1, __GET_VAR(data__->TRIG)); + /* python thread is not in ? */ + if( PythonState & PYTHON_LOCKED_BY_PLC){ + /* if some answer are waiting, publish*/ + if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){ + /* Copy buffer content into result*/ + __SET_VAR(data__->, RESULT, __GET_VAR(data__->BUFFER)); + /* signal result presece to PLC*/ + __SET_VAR(data__->, ACK, 1); + __SET_VAR(data__->, STATE, PYTHON_FB_FREE); + /* mark as not trigged */ + __SET_VAR(data__->, TRIGGED, 0); + /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/ + /* when in polling, no answer == ack down */ + __SET_VAR(data__->, ACK, 0); + /* got the order to act ?*/ + if(__GET_VAR(data__->TRIGGED) == 1 && + /* and not already being processed */ + __GET_VAR(data__->STATE) == PYTHON_FB_FREE) + /* Enter the block in the fifo + * Don't have to check if fifo cell is free + * as fifo size == FB count, and a FB cannot + * be requested twice */ + EvalFBs[Current_PLC_EvalFB] = data__; + /* copy into BUFFER local*/ + __SET_VAR(data__->, BUFFER, __GET_VAR(data__->PREBUFFER)); + /* Set ACK pin to low so that we can set a rising edge on result */ + /* when not polling, a new answer imply reseting ack*/ + __SET_VAR(data__->, ACK, 0); + /* when in polling, acting reset trigger */ + __SET_VAR(data__->, TRIGGED, 0); + __SET_VAR(data__->, STATE, PYTHON_FB_REQUESTED); + /* Have to wakeup python thread in case he was asleep */ + PythonState |= PYTHON_MUSTWAKEUP; + /*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/ + Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d; +char* PythonIterator(char* result) + //printf("PythonIterator result %%s\n", result); + if(PythonState & PYTHON_FINISHED) return NULL; + /* take python mutex to prevent changing PLC data while PLC running */ + data__ = EvalFBs[Current_Python_EvalFB]; + if(data__ && /* may be null at first run */ + __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/ + /* If result not None */ + __SET_VAR(data__->, BUFFER, strlen(result), .len); + /* prevent results overrun */ + if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN) + __SET_VAR(data__->, BUFFER, STR_MAX_LEN, .len ); + /* TODO : signal error */ + /* Copy results to buffer */ + strncpy((char*)__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len)); + __SET_VAR(data__->, BUFFER, 0, .len); + /* remove block from fifo*/ + EvalFBs[Current_Python_EvalFB] = NULL; + /* Mark block as answered */ + __SET_VAR(data__->, STATE, PYTHON_FB_ANSWERED); + Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d; + //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB); + /* while next slot is empty */ + while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || + /* or doesn't contain command */ + __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED) + /* wait next FB to eval */ + //printf("PythonIterator wait\n"); + if(WaitPythonCommands()) return NULL; + if(PythonState & PYTHON_FINISHED) return NULL; + /* Mark block as processing */ + __SET_VAR(data__->, STATE, PYTHON_FB_PROCESSING); + //printf("PythonIterator\n"); + /* make BUFFER a null terminated string */ + __SET_VAR(data__->, BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]); + /* next command is BUFFER */ + next_command = (char*)__GET_VAR(data__->BUFFER, .body); + /* free python mutex */ + /* return the next command to eval */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/pous.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://www.plcopen.org/xml/tc6.xsd" + xmlns:xhtml="http://www.w3.org/1999/xhtml" + xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd"> + <fileHeader companyName="Beremiz" + creationDateTime="2008-12-14T16:53:26"/> + <contentHeader name="Beremiz non-standard POUs library" + modificationDateTime="2008-12-23T22:35:46"> + <pou name="python_eval" pouType="functionBlock"> + <variable name="RESULT"> + <variable name="STATE"> + <variable name="BUFFER"> + <variable name="PREBUFFER"> + <variable name="TRIGM1"> + <variable name="TRIGGED"> +<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(0, data__);}]]> + <pou name="python_poll" pouType="functionBlock"> + <variable name="RESULT"> + <variable name="STATE"> + <variable name="BUFFER"> + <variable name="PREBUFFER"> + <variable name="TRIGM1"> + <variable name="TRIGGED"> +<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(1,(PYTHON_EVAL*)(void*)data__);}]]> + <pou name="python_gear" pouType="functionBlock"> + <variable name="RESULT"> + <variable name="py_eval"> + <derived name="python_eval"/> + <variable name="COUNTER"> + <block localId="1" width="125" height="110" typeName="python_eval" instanceName="py_eval"> + <position x="525" y="580"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="40"/> + <connection refLocalId="7" formalParameter="OUT"> + <position x="525" y="620"/> + <position x="495" y="620"/> + <position x="495" y="575"/> + <position x="465" y="575"/> + <variable formalParameter="CODE"> + <relPosition x="0" y="85"/> + <connection refLocalId="4"> + <position x="525" y="665"/> + <position x="370" y="665"/> + <variable formalParameter="ACK"> + <relPosition x="125" y="40"/> + <variable formalParameter="RESULT"> + <relPosition x="125" y="85"/> + <inVariable localId="2" height="35" width="25"> + <position x="435" y="270"/> + <relPosition x="25" y="15"/> + <expression>N</expression> + <inVariable localId="3" height="35" width="55"> + <position x="275" y="585"/> + <relPosition x="55" y="15"/> + <expression>TRIG</expression> + <inVariable localId="4" height="35" width="55"> + <position x="315" y="650"/> + <relPosition x="55" y="15"/> + <expression>CODE</expression> + <outVariable localId="5" height="35" width="45"> + <position x="740" y="605"/> + <relPosition x="0" y="15"/> + <connection refLocalId="1" formalParameter="ACK"> + <position x="740" y="620"/> + <position x="650" y="620"/> + <expression>ACK</expression> + <outVariable localId="6" height="35" width="75"> + <position x="740" y="650"/> + <relPosition x="0" y="15"/> + <connection refLocalId="1" formalParameter="RESULT"> + <position x="740" y="665"/> + <position x="650" y="665"/> + <expression>RESULT</expression> + <block localId="7" width="80" height="65" typeName="AND"> + <position x="385" y="545"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="30"/> + <connection refLocalId="13" formalParameter="OUT"> + <position x="385" y="575"/> + <position x="335" y="575"/> + <position x="335" y="455"/> + <position x="625" y="455"/> + <position x="625" y="285"/> + <position x="615" y="285"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="55"/> + <connection refLocalId="3"> + <position x="385" y="600"/> + <position x="330" y="600"/> + <variable formalParameter="OUT"> + <relPosition x="80" y="30"/> + <inVariable localId="9" height="35" width="85"> + <position x="240" y="330"/> + <relPosition x="85" y="15"/> + <expression>COUNTER</expression> + <block localId="10" width="80" height="65" typeName="ADD"> + <position x="380" y="330"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="30"/> + <connection refLocalId="9"> + <position x="380" y="360"/> + <position x="352" y="360"/> + <position x="352" y="345"/> + <position x="325" y="345"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="55"/> + <connection refLocalId="11"> + <position x="380" y="385"/> + <position x="325" y="385"/> + <variable formalParameter="OUT"> + <relPosition x="80" y="30"/> + <inVariable localId="11" height="35" width="85"> + <position x="240" y="370"/> + <relPosition x="85" y="15"/> + <expression>USINT#1</expression> + <block localId="13" width="80" height="65" typeName="EQ"> + <position x="535" y="255"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="30"/> + <connection refLocalId="2"> + <position x="535" y="285"/> + <position x="460" y="285"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="55"/> + <connection refLocalId="10" formalParameter="OUT"> + <position x="535" y="310"/> + <position x="497" y="310"/> + <position x="497" y="360"/> + <position x="460" y="360"/> + <variable formalParameter="OUT"> + <relPosition x="80" y="30"/> + <block localId="15" width="80" height="135" typeName="SEL"> + <position x="785" y="245"/> + <variable formalParameter="G"> + <relPosition x="0" y="40"/> + <connection refLocalId="13" formalParameter="OUT"> + <position x="785" y="285"/> + <position x="615" y="285"/> + <variable formalParameter="IN0"> + <relPosition x="0" y="75"/> + <connection refLocalId="10" formalParameter="OUT"> + <position x="785" y="320"/> + <position x="650" y="320"/> + <position x="650" y="360"/> + <position x="460" y="360"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="115"/> + <connection refLocalId="16"> + <position x="785" y="360"/> + <position x="760" y="360"/> + <variable formalParameter="OUT"> + <relPosition x="80" y="40"/> + <inVariable localId="16" height="35" width="85"> + <position x="675" y="345"/> + <relPosition x="85" y="15"/> + <expression>USINT#0</expression> + <outVariable localId="17" height="35" width="85"> + <position x="905" y="270"/> + <relPosition x="0" y="15"/> + <connection refLocalId="15" formalParameter="OUT"> + <position x="905" y="285"/> + <position x="865" y="285"/> + <expression>COUNTER</expression> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/py_ext.py Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,185 @@
+from ConfigTree import ConfigTreeNode, opjimg +from PLCControler import UndoBuffer +from PythonEditor import PythonEditor +from xml.dom import minidom +PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd")) +class PythonCodeTemplate: + EditorType = PythonEditor + 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) + 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) + self.CreatePythonBuffer(False) + 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") + if self.PythonBuffer.IsCurrentSaved(): + 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() + filepath = self.PythonFileName() + text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\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")) + self.MarkPythonAsSaved() +#------------------------------------------------------------------------------- +# Current Buffering Management Functions +#------------------------------------------------------------------------------- + Return a copy of the project + return cPickle.loads(cPickle.dumps(model)) + def CreatePythonBuffer(self, saved): + self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved) + def BufferPython(self): + self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) + def StartBuffering(self): + def EndBuffering(self): + self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) + def MarkPythonAsSaved(self): + self.PythonBuffer.CurrentSaved() + def PythonIsSaved(self): + return self.PythonBuffer.IsCurrentSaved() and not self.Buffering + def LoadPrevious(self): + self.PythonCode = cPickle.loads(self.PythonBuffer.Previous()) + 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): + __import__("py_ext.modules." + name) + return getattr(modules, name).RootClass +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): + @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.GetIECProgramsAndVariables() + 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: + 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)) + plc_python_code = plc_python_code % { + "python_eval_fb_count": python_eval_fb_count, + "location": location_str} + Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str) + pythonfile = open(Gen_Pythonfile_path,'w') + pythonfile.write(plc_python_code) + runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) + runtimefile = open(runtimefile_path, 'w') + runtimefile.write(self.GetPythonCode()) + 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")) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/py_ext/py_ext_xsd.xsd Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?> +<xsd:schema targetNamespace="python_xsd.xsd" + xmlns:cext="python_xsd.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> + <xsd:element name="Python"> + <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation> + <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/python@py_ext/baseconfnode.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?> +<BaseParams Name="python" IEC_Channel="0"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/python@py_ext/py_ext.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd"> +<![CDATA[import time,sys --- a/tests/python/python@python/baseconfnode.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="python" IEC_Channel="0"/>
--- a/tests/python/python@python/python.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd">
-<![CDATA[import time,sys
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@py_ext/baseconfnode.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?> +<BaseParams Name="python" IEC_Channel="0"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@py_ext/py_ext.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd"> +<![CDATA[import time,sys --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@py_ext/svgui@svgui/baseconfnode.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?> +<BaseParams Name="svgui" IEC_Channel="0"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@py_ext/svgui@svgui/gui.svg Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,723 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:version="0.32" + inkscape:version="0.47pre4 " + sodipodi:docname="gui.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:cx="200.66323" + inkscape:cy="178.08292" + inkscape:document-units="px" + inkscape:current-layer="layer1" + inkscape:window-width="1071" + inkscape:window-height="805" + inkscape:window-x="106" + inkscape:window-maximized="0" /> + id="linearGradient3770"> + style="stop-color:#008000;stop-opacity:1;" + style="stop-color:#00fb00;stop-opacity:1;" + id="linearGradient3708"> + style="stop-color:#d40000;stop-opacity:1;" + style="stop-color:#ff5c5c;stop-opacity:1;" + id="linearGradient4202"> + style="stop-color:#f6edda;stop-opacity:1;" /> + style="stop-color:#e6e6e6;stop-opacity:1;" /> + id="linearGradient4192"> + style="stop-color:#faf4e9;stop-opacity:1;" + style="stop-color:#f1f1f1;stop-opacity:1;" + id="linearGradient3302"> + style="stop-color:#ff0000;stop-opacity:0;" + style="stop-color:#ff0000;stop-opacity:0.49803922;" /> + style="stop-color:#ff0000;stop-opacity:1;" + style="stop-color:#ff0000;stop-opacity:0;" + id="linearGradient3687"> + style="stop-color:#23d5ff;stop-opacity:1;" /> + style="stop-color:#b1ffff;stop-opacity:1;" /> + id="linearGradient3679"> + style="stop-color:#00b5ff;stop-opacity:1;" /> + style="stop-color:#005bff;stop-opacity:1;" /> + id="linearGradient3659"> + style="stop-color:#ff0030;stop-opacity:1;" /> + style="stop-color:#e20000;stop-opacity:0.83211678;" + style="stop-color:#ffffff;stop-opacity:0;" /> + id="linearGradient3639"> + style="stop-color:#ffff00;stop-opacity:1;" /> + style="stop-color:#8fff00;stop-opacity:0.49803922;" + style="stop-color:#ffffff;stop-opacity:0;" /> + id="linearGradient3621"> + style="stop-color:#ff8080;stop-opacity:1;" /> + style="stop-color:#aa0000;stop-opacity:1;" /> + id="linearGradient3613" + inkscape:collect="always"> + style="stop-color:#000000;stop-opacity:1;" /> + style="stop-color:#000000;stop-opacity:0;" /> + id="linearGradient3497"> + style="stop-color:#00cd00;stop-opacity:1;" /> + style="stop-color:#007900;stop-opacity:1;" /> + id="linearGradient3453"> + style="stop-color:#000000;stop-opacity:1;" /> + style="stop-color:#ffffff;stop-opacity:0;" /> + id="linearGradient3173"> + style="stop-color:#ffffff;stop-opacity:1;" + style="stop-color:#ffffff;stop-opacity:0;" /> + style="stop-color:#ff0000;stop-opacity:0;" + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2619" /> + gradientUnits="userSpaceOnUse" + id="linearGradient3503" + xlink:href="#linearGradient3497" + inkscape:collect="always" /> + gradientUnits="userSpaceOnUse" + id="linearGradient3619" + xlink:href="#linearGradient3613" + inkscape:collect="always" /> + gradientUnits="userSpaceOnUse" + id="linearGradient3627" + xlink:href="#linearGradient3621" + inkscape:collect="always" /> + gradientTransform="translate(-18,26)" + gradientUnits="userSpaceOnUse" + id="linearGradient3633" + xlink:href="#linearGradient3621" + inkscape:collect="always" /> + gradientUnits="userSpaceOnUse" + id="radialGradient3667" + xlink:href="#linearGradient3639" + inkscape:collect="always" /> + gradientUnits="userSpaceOnUse" + id="radialGradient3675" + xlink:href="#linearGradient3659" + inkscape:collect="always" /> + gradientTransform="translate(-1.3119965,1.110878)" + gradientUnits="userSpaceOnUse" + id="linearGradient3693" + xlink:href="#linearGradient3687" + inkscape:collect="always" /> + gradientUnits="userSpaceOnUse" + id="linearGradient3702" + xlink:href="#linearGradient4202" + inkscape:collect="always" /> + gradientTransform="translate(-1.3119965,1.110878)" + gradientUnits="userSpaceOnUse" + id="linearGradient3704" + xlink:href="#linearGradient3613" + inkscape:collect="always" /> + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective3767" /> + inkscape:collect="always" + xlink:href="#linearGradient3302" + id="linearGradient3308" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-25.178571,-3.0357143)" /> + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3536" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3538" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3540" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3542" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3544" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3546" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3548" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3550" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(5.555838,16.162441)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3694" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3696" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3698" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3700" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3703" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3705" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3707" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient3613" + id="linearGradient3709" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-381.09403,-544.64978)" + inkscape:collect="always" + xlink:href="#linearGradient4192" + id="linearGradient4200" + gradientUnits="userSpaceOnUse" /> + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + inkscape:collect="always" + xlink:href="#linearGradient3708" + id="linearGradient3714" + gradientUnits="userSpaceOnUse" /> + inkscape:collect="always" + xlink:href="#linearGradient3708" + id="linearGradient3722" + gradientUnits="userSpaceOnUse" /> + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + inkscape:collect="always" + xlink:href="#linearGradient3770" + id="linearGradient3776" + gradientUnits="userSpaceOnUse" /> + inkscape:collect="always" + xlink:href="#linearGradient3770" + id="linearGradient3784" + gradientUnits="userSpaceOnUse" /> + inkscape:collect="always" + xlink:href="#linearGradient3621" + id="radialGradient3792" + gradientUnits="userSpaceOnUse" /> + inkscape:collect="always" + xlink:href="#linearGradient3497" + id="radialGradient3800" + gradientUnits="userSpaceOnUse" /> + <dc:format>image/svg+xml</dc:format> + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + inkscape:label="Calque 1" + inkscape:groupmode="layer" + style="display:inline"> + style="fill:url(#linearGradient4200);fill-opacity:1;stroke:#000000;stroke-width:1.46953177;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + transform="translate(-127.27923,-40.406102)" + style="fill:url(#linearGradient3702);fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0" + sodipodi:linespacing="125%" + style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:#655fdb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + xml:space="preserve"><tspan + style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#655fdb;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold">Default</tspan></text> + transform="translate(-33.11078,95.2077)"> + style="color:#000000;fill:url(#linearGradient3776);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3784);stroke-width:3.80890393;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + sodipodi:cx="103.21429" + sodipodi:cy="127.14286" + sodipodi:r1="91.508057" + sodipodi:r2="45.754028" + sodipodi:arg2="1.0471976" + inkscape:flatsided="true" + inkscape:randomized="0" + d="m 194.72234,127.14286 -137.262082,79.2483 0,-158.496601 137.262082,79.248301 z" + transform="matrix(0.78762818,0,0,0.78762818,26.492161,-44.168468)" /> + sodipodi:linespacing="100%" + style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:end;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:end;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:inherit;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + xml:space="preserve"><tspan + style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:end;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:end;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:inherit;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + sodipodi:role="line">Start</tspan></text> + transform="translate(-18.07106,94.06456)" + style="color:#000000;fill:url(#linearGradient3714);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3722);stroke-width:3.94511151;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + sodipodi:cx="83.571426" + sodipodi:cy="224.28571" + sodipodi:r1="94.724358" + sodipodi:r2="87.513893" + sodipodi:arg2="0.39269908" + inkscape:flatsided="true" + inkscape:randomized="0" + d="m 178.29578,224.28571 -27.74412,66.98023 -66.980234,27.74412 -66.980235,-27.74412 -27.744122,-66.98023 27.744122,-66.98024 66.980235,-27.74412 66.980234,27.74412 27.74412,66.98024 z" + transform="matrix(0.70255013,-0.29100577,0.29100577,0.70255013,-13.216048,-76.13621)" /> + sodipodi:linespacing="100%" + style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:end;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:end;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:inherit;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + xml:space="preserve"><tspan + style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:end;line-height:100%;writing-mode:lr-tb;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + sodipodi:role="line">Stop</tspan></text> + transform="matrix(2.0899173,0,0,2.0899173,-577.84265,-204.88668)" + transform="translate(42.282829,64.376725)" + d="m 369.71585,101.69787 a 17.67767,17.67767 0 1 1 -35.35534,0 17.67767,17.67767 0 1 1 35.35534,0 z" + sodipodi:cy="101.69787" + sodipodi:cx="352.03818" + style="fill:url(#radialGradient3800);fill-opacity:1;stroke:#000000;stroke-width:0.47848782;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + transform="matrix(2.0899173,0,0,2.0899173,-637.08625,-59.866062)" + style="fill:url(#radialGradient3792);fill-opacity:1;stroke:#000000;stroke-width:0.47848782;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + sodipodi:cx="352.03818" + sodipodi:cy="101.69787" + d="m 369.71585,101.69787 a 17.67767,17.67767 0 1 1 -35.35534,0 17.67767,17.67767 0 1 1 35.35534,0 z" + transform="translate(70.630181,-5.0138784)" /> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@py_ext/svgui@svgui/py_ext.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd"> --- a/tests/svgui/python@python/baseconfnode.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="python" IEC_Channel="0"/>
--- a/tests/svgui/python@python/python.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd">
-<![CDATA[import time,sys
--- a/tests/svgui/python@python/svgui@svgui/baseconfnode.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="svgui" IEC_Channel="0"/>
--- a/tests/svgui/python@python/svgui@svgui/gui.svg Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,723 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- sodipodi:version="0.32"
- inkscape:version="0.47pre4 "
- sodipodi:docname="gui.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:cx="200.66323"
- inkscape:cy="178.08292"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="1071"
- inkscape:window-height="805"
- inkscape:window-x="106"
- inkscape:window-maximized="0" />
- id="linearGradient3770">
- style="stop-color:#008000;stop-opacity:1;"
- style="stop-color:#00fb00;stop-opacity:1;"
- id="linearGradient3708">
- style="stop-color:#d40000;stop-opacity:1;"
- style="stop-color:#ff5c5c;stop-opacity:1;"
- id="linearGradient4202">
- style="stop-color:#f6edda;stop-opacity:1;" />
- style="stop-color:#e6e6e6;stop-opacity:1;" />
- id="linearGradient4192">
- style="stop-color:#faf4e9;stop-opacity:1;"
- style="stop-color:#f1f1f1;stop-opacity:1;"
- id="linearGradient3302">
- style="stop-color:#ff0000;stop-opacity:0;"
- style="stop-color:#ff0000;stop-opacity:0.49803922;" />
- style="stop-color:#ff0000;stop-opacity:1;"
- style="stop-color:#ff0000;stop-opacity:0;"
- id="linearGradient3687">
- style="stop-color:#23d5ff;stop-opacity:1;" />
- style="stop-color:#b1ffff;stop-opacity:1;" />
- id="linearGradient3679">
- style="stop-color:#00b5ff;stop-opacity:1;" />
- style="stop-color:#005bff;stop-opacity:1;" />
- id="linearGradient3659">
- style="stop-color:#ff0030;stop-opacity:1;" />
- style="stop-color:#e20000;stop-opacity:0.83211678;"
- style="stop-color:#ffffff;stop-opacity:0;" />
- id="linearGradient3639">
- style="stop-color:#ffff00;stop-opacity:1;" />
- style="stop-color:#8fff00;stop-opacity:0.49803922;"
- style="stop-color:#ffffff;stop-opacity:0;" />
- id="linearGradient3621">
- style="stop-color:#ff8080;stop-opacity:1;" />
- style="stop-color:#aa0000;stop-opacity:1;" />
- id="linearGradient3613"
- inkscape:collect="always">
- style="stop-color:#000000;stop-opacity:1;" />
- style="stop-color:#000000;stop-opacity:0;" />
- id="linearGradient3497">
- style="stop-color:#00cd00;stop-opacity:1;" />
- style="stop-color:#007900;stop-opacity:1;" />
- id="linearGradient3453">
- style="stop-color:#000000;stop-opacity:1;" />
- style="stop-color:#ffffff;stop-opacity:0;" />
- id="linearGradient3173">
- style="stop-color:#ffffff;stop-opacity:1;"
- style="stop-color:#ffffff;stop-opacity:0;" />
- style="stop-color:#ff0000;stop-opacity:0;"
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- id="perspective2619" />
- gradientUnits="userSpaceOnUse"
- id="linearGradient3503"
- xlink:href="#linearGradient3497"
- inkscape:collect="always" />
- gradientUnits="userSpaceOnUse"
- id="linearGradient3619"
- xlink:href="#linearGradient3613"
- inkscape:collect="always" />
- gradientUnits="userSpaceOnUse"
- id="linearGradient3627"
- xlink:href="#linearGradient3621"
- inkscape:collect="always" />
- gradientTransform="translate(-18,26)"
- gradientUnits="userSpaceOnUse"
- id="linearGradient3633"
- xlink:href="#linearGradient3621"
- inkscape:collect="always" />
- gradientUnits="userSpaceOnUse"
- id="radialGradient3667"
- xlink:href="#linearGradient3639"
- inkscape:collect="always" />
- gradientUnits="userSpaceOnUse"
- id="radialGradient3675"
- xlink:href="#linearGradient3659"
- inkscape:collect="always" />
- gradientTransform="translate(-1.3119965,1.110878)"
- gradientUnits="userSpaceOnUse"
- id="linearGradient3693"
- xlink:href="#linearGradient3687"
- inkscape:collect="always" />
- gradientUnits="userSpaceOnUse"
- id="linearGradient3702"
- xlink:href="#linearGradient4202"
- inkscape:collect="always" />
- gradientTransform="translate(-1.3119965,1.110878)"
- gradientUnits="userSpaceOnUse"
- id="linearGradient3704"
- xlink:href="#linearGradient3613"
- inkscape:collect="always" />
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- id="perspective3767" />
- inkscape:collect="always"
- xlink:href="#linearGradient3302"
- id="linearGradient3308"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-25.178571,-3.0357143)" />
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3536"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3538"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3540"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3542"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3544"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3546"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3548"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3550"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(5.555838,16.162441)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3694"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3696"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3698"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3700"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3703"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3705"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3707"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient3613"
- id="linearGradient3709"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-381.09403,-544.64978)"
- inkscape:collect="always"
- xlink:href="#linearGradient4192"
- id="linearGradient4200"
- gradientUnits="userSpaceOnUse" />
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- inkscape:collect="always"
- xlink:href="#linearGradient3708"
- id="linearGradient3714"
- gradientUnits="userSpaceOnUse" />
- inkscape:collect="always"
- xlink:href="#linearGradient3708"
- id="linearGradient3722"
- gradientUnits="userSpaceOnUse" />
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- inkscape:collect="always"
- xlink:href="#linearGradient3770"
- id="linearGradient3776"
- gradientUnits="userSpaceOnUse" />
- inkscape:collect="always"
- xlink:href="#linearGradient3770"
- id="linearGradient3784"
- gradientUnits="userSpaceOnUse" />
- inkscape:collect="always"
- xlink:href="#linearGradient3621"
- id="radialGradient3792"
- gradientUnits="userSpaceOnUse" />
- inkscape:collect="always"
- xlink:href="#linearGradient3497"
- id="radialGradient3800"
- gradientUnits="userSpaceOnUse" />
- <dc:format>image/svg+xml</dc:format>
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- inkscape:label="Calque 1"
- inkscape:groupmode="layer"
- style="display:inline">
- style="fill:url(#linearGradient4200);fill-opacity:1;stroke:#000000;stroke-width:1.46953177;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- transform="translate(-127.27923,-40.406102)"
- style="fill:url(#linearGradient3702);fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0"
- sodipodi:linespacing="125%"
- style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:#655fdb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold"
- xml:space="preserve"><tspan
- style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#655fdb;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold">Default</tspan></text>
- transform="translate(-33.11078,95.2077)">
- style="color:#000000;fill:url(#linearGradient3776);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3784);stroke-width:3.80890393;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:cx="103.21429"
- sodipodi:cy="127.14286"
- sodipodi:r1="91.508057"
- sodipodi:r2="45.754028"
- sodipodi:arg2="1.0471976"
- inkscape:flatsided="true"
- inkscape:randomized="0"
- d="m 194.72234,127.14286 -137.262082,79.2483 0,-158.496601 137.262082,79.248301 z"
- transform="matrix(0.78762818,0,0,0.78762818,26.492161,-44.168468)" />
- sodipodi:linespacing="100%"
- style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:end;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:end;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:inherit;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold"
- xml:space="preserve"><tspan
- style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:end;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:end;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:inherit;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold"
- sodipodi:role="line">Start</tspan></text>
- transform="translate(-18.07106,94.06456)"
- style="color:#000000;fill:url(#linearGradient3714);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3722);stroke-width:3.94511151;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:cx="83.571426"
- sodipodi:cy="224.28571"
- sodipodi:r1="94.724358"
- sodipodi:r2="87.513893"
- sodipodi:arg2="0.39269908"
- inkscape:flatsided="true"
- inkscape:randomized="0"
- d="m 178.29578,224.28571 -27.74412,66.98023 -66.980234,27.74412 -66.980235,-27.74412 -27.744122,-66.98023 27.744122,-66.98024 66.980235,-27.74412 66.980234,27.74412 27.74412,66.98024 z"
- transform="matrix(0.70255013,-0.29100577,0.29100577,0.70255013,-13.216048,-76.13621)" />
- sodipodi:linespacing="100%"
- style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:end;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:end;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:inherit;display:inline;overflow:visible;enable-background:accumulate;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold"
- xml:space="preserve"><tspan
- style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:end;line-height:100%;writing-mode:lr-tb;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold"
- sodipodi:role="line">Stop</tspan></text>
- transform="matrix(2.0899173,0,0,2.0899173,-577.84265,-204.88668)"
- transform="translate(42.282829,64.376725)"
- d="m 369.71585,101.69787 a 17.67767,17.67767 0 1 1 -35.35534,0 17.67767,17.67767 0 1 1 35.35534,0 z"
- sodipodi:cy="101.69787"
- sodipodi:cx="352.03818"
- style="fill:url(#radialGradient3800);fill-opacity:1;stroke:#000000;stroke-width:0.47848782;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- transform="matrix(2.0899173,0,0,2.0899173,-637.08625,-59.866062)"
- style="fill:url(#radialGradient3792);fill-opacity:1;stroke:#000000;stroke-width:0.47848782;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- sodipodi:cx="352.03818"
- sodipodi:cy="101.69787"
- d="m 369.71585,101.69787 a 17.67767,17.67767 0 1 1 -35.35534,0 17.67767,17.67767 0 1 1 35.35534,0 z"
- transform="translate(70.630181,-5.0138784)" />
--- a/tests/svgui/python@python/svgui@svgui/python.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/baseconfnode.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?> +<BaseParams Name="HMIFrame" IEC_Channel="0"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/hmi.wxg Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,34 @@
+<!-- generated by wxGlade 0.6.3 on Fri Aug 7 18:16:44 2009 --> +<application path="" name="" class="" option="0" language="python" top_window="HMIFrame" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0"> + <object class="Class_HMIFrame" name="HMIFrame" base="EditFrame"> + <style>wxDEFAULT_FRAME_STYLE</style> + <title>HMIFrame</title> + <object class="wxBoxSizer" name="sizer_1" base="EditBoxSizer"> + <orient>wxVERTICAL</orient> + <object class="sizeritem"> + <object class="wxSpinCtrl" name="spin_ctrl_1" base="EditSpinCtrl"> + <range>0, 10000</range> + <object class="sizeritem"> + <object class="wxCheckBox" name="checkbox_1" base="EditCheckBox"> + <label>checkbox_1</label> + <object class="sizeritem"> + <object class="wxStaticText" name="label_1" base="EditStaticText"> + <attribute>1</attribute> + <label>GUI modifiée !</label> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/py_ext.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd"> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@py_ext/baseconfnode.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?> +<BaseParams Name="python" IEC_Channel="0"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@py_ext/py_ext.xml Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd"> --- a/tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseconfnode.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="HMIFrame" IEC_Channel="0"/>
--- a/tests/wxGlade/python@python/HMIFrame@wxglade_hmi/hmi.wxg Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-<!-- generated by wxGlade 0.6.3 on Fri Aug 7 18:16:44 2009 -->
-<application path="" name="" class="" option="0" language="python" top_window="HMIFrame" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
- <object class="Class_HMIFrame" name="HMIFrame" base="EditFrame">
- <style>wxDEFAULT_FRAME_STYLE</style>
- <title>HMIFrame</title>
- <object class="wxBoxSizer" name="sizer_1" base="EditBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <object class="wxSpinCtrl" name="spin_ctrl_1" base="EditSpinCtrl">
- <range>0, 10000</range>
- <object class="sizeritem">
- <object class="wxCheckBox" name="checkbox_1" base="EditCheckBox">
- <label>checkbox_1</label>
- <object class="sizeritem">
- <object class="wxStaticText" name="label_1" base="EditStaticText">
- <attribute>1</attribute>
- <label>GUI modifiée !</label>
--- a/tests/wxGlade/python@python/HMIFrame@wxglade_hmi/python.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd">
--- a/tests/wxGlade/python@python/baseconfnode.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="python" IEC_Channel="0"/>
--- a/tests/wxGlade/python@python/python.xml Tue May 08 16:31:12 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="python_xsd.xsd">