beremiz

refactoring

2012-05-08, Edouard Tisserant
ecf4d203c4d4
Parents 6be032177e2a
Children a94f361fc42e
refactoring
  • +4 -5
    ConfigTree.py
  • +3 -3
    LPCBeremiz.py
  • +1 -0
    c_ext/.cvsignore
  • +967 -0
    c_ext/CFileEditor.py
  • +1 -0
    c_ext/README
  • +1 -0
    c_ext/__init__.py
  • +315 -0
    c_ext/c_ext.py
  • +49 -0
    c_ext/cext_xsd.xsd
  • +1 -0
    canfestival/.cvsignore
  • +122 -0
    canfestival/NetworkEditor.py
  • +1 -0
    canfestival/README
  • +83 -0
    canfestival/SlaveEditor.py
  • +1 -0
    canfestival/__init__.py
  • +484 -0
    canfestival/canfestival.py
  • +150 -0
    canfestival/cf_runtime.c
  • +737 -0
    canfestival/config_utils.py
  • +1289 -0
    canfestival/test_config/eds/PEAK MicroMod.eds
  • +314 -0
    canfestival/test_config/master.od
  • +7 -0
    canfestival/test_config/nodelist.cpj
  • +257 -0
    canfestival/test_config/result.txt
  • +0 -1
    confnodes/.cvsignore
  • +0 -10
    confnodes/__init__.py
  • +0 -1
    confnodes/c_ext/.cvsignore
  • +0 -967
    confnodes/c_ext/CFileEditor.py
  • +0 -1
    confnodes/c_ext/README
  • +0 -1
    confnodes/c_ext/__init__.py
  • +0 -315
    confnodes/c_ext/c_ext.py
  • +0 -49
    confnodes/c_ext/cext_xsd.xsd
  • +0 -1
    confnodes/canfestival/.cvsignore
  • +0 -122
    confnodes/canfestival/NetworkEditor.py
  • +0 -1
    confnodes/canfestival/README
  • +0 -83
    confnodes/canfestival/SlaveEditor.py
  • +0 -1
    confnodes/canfestival/__init__.py
  • +0 -484
    confnodes/canfestival/canfestival.py
  • +0 -150
    confnodes/canfestival/cf_runtime.c
  • +0 -737
    confnodes/canfestival/config_utils.py
  • +0 -1289
    confnodes/canfestival/test_config/eds/PEAK MicroMod.eds
  • +0 -314
    confnodes/canfestival/test_config/master.od
  • +0 -7
    confnodes/canfestival/test_config/nodelist.cpj
  • +0 -257
    confnodes/canfestival/test_config/result.txt
  • +0 -505
    confnodes/python/PythonEditor.py
  • +0 -1
    confnodes/python/README
  • +0 -1
    confnodes/python/__init__.py
  • +0 -13
    confnodes/python/modules/__init__.py
  • +0 -1
    confnodes/python/modules/svgui/README
  • +0 -1
    confnodes/python/modules/svgui/__init__.py
  • +0 -59
    confnodes/python/modules/svgui/livesvg.js
  • +0 -1428
    confnodes/python/modules/svgui/pous.xml
  • +0 -2
    confnodes/python/modules/svgui/pyjs/__init__.py
  • +0 -724
    confnodes/python/modules/svgui/pyjs/build.py
  • +0 -12
    confnodes/python/modules/svgui/pyjs/jsonrpc/README.txt
  • +0 -226
    confnodes/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py
  • +0 -43
    confnodes/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py
  • +0 -11
    confnodes/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py
  • +0 -160
    confnodes/python/modules/svgui/pyjs/lib/_pyjs.js
  • +0 -293
    confnodes/python/modules/svgui/pyjs/lib/json.js
  • +0 -1365
    confnodes/python/modules/svgui/pyjs/lib/pyjslib.py
  • +0 -59
    confnodes/python/modules/svgui/pyjs/lib/sys.py
  • +0 -1777
    confnodes/python/modules/svgui/pyjs/pyjs.py
  • +0 -112
    confnodes/python/modules/svgui/svgui.py
  • +0 -130
    confnodes/python/modules/svgui/svgui_server.py
  • +0 -117
    confnodes/python/modules/svgui/svguilib.py
  • +0 -1
    confnodes/python/modules/wxglade_hmi/README
  • +0 -1
    confnodes/python/modules/wxglade_hmi/__init__.py
  • +0 -124
    confnodes/python/modules/wxglade_hmi/wxglade_hmi.py
  • +0 -216
    confnodes/python/plc_python.c
  • +0 -457
    confnodes/python/pous.xml
  • +0 -185
    confnodes/python/python.py
  • +0 -18
    confnodes/python/python_xsd.xsd
  • +7 -0
    features.py
  • +505 -0
    py_ext/PythonEditor.py
  • +1 -0
    py_ext/README
  • +1 -0
    py_ext/__init__.py
  • +13 -0
    py_ext/modules/__init__.py
  • +1 -0
    py_ext/modules/svgui/README
  • +1 -0
    py_ext/modules/svgui/__init__.py
  • +59 -0
    py_ext/modules/svgui/livesvg.js
  • +1428 -0
    py_ext/modules/svgui/pous.xml
  • +2 -0
    py_ext/modules/svgui/pyjs/__init__.py
  • +724 -0
    py_ext/modules/svgui/pyjs/build.py
  • +12 -0
    py_ext/modules/svgui/pyjs/jsonrpc/README.txt
  • +226 -0
    py_ext/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py
  • +43 -0
    py_ext/modules/svgui/pyjs/jsonrpc/jsonrpc.py
  • +11 -0
    py_ext/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py
  • +160 -0
    py_ext/modules/svgui/pyjs/lib/_pyjs.js
  • +293 -0
    py_ext/modules/svgui/pyjs/lib/json.js
  • +1365 -0
    py_ext/modules/svgui/pyjs/lib/pyjslib.py
  • +59 -0
    py_ext/modules/svgui/pyjs/lib/sys.py
  • +1777 -0
    py_ext/modules/svgui/pyjs/pyjs.py
  • +112 -0
    py_ext/modules/svgui/svgui.py
  • +130 -0
    py_ext/modules/svgui/svgui_server.py
  • +117 -0
    py_ext/modules/svgui/svguilib.py
  • +1 -0
    py_ext/modules/wxglade_hmi/README
  • +1 -0
    py_ext/modules/wxglade_hmi/__init__.py
  • +124 -0
    py_ext/modules/wxglade_hmi/wxglade_hmi.py
  • +216 -0
    py_ext/plc_python.c
  • +457 -0
    py_ext/pous.xml
  • +185 -0
    py_ext/py_ext.py
  • +18 -0
    py_ext/py_ext_xsd.xsd
  • +2 -0
    tests/python/python@py_ext/baseconfnode.xml
  • +8 -0
    tests/python/python@py_ext/py_ext.xml
  • +0 -2
    tests/python/python@python/baseconfnode.xml
  • +0 -8
    tests/python/python@python/python.xml
  • +2 -0
    tests/svgui/python@py_ext/baseconfnode.xml
  • +8 -0
    tests/svgui/python@py_ext/py_ext.xml
  • +2 -0
    tests/svgui/python@py_ext/svgui@svgui/baseconfnode.xml
  • +723 -0
    tests/svgui/python@py_ext/svgui@svgui/gui.svg
  • +4 -0
    tests/svgui/python@py_ext/svgui@svgui/py_ext.xml
  • +0 -2
    tests/svgui/python@python/baseconfnode.xml
  • +0 -8
    tests/svgui/python@python/python.xml
  • +0 -2
    tests/svgui/python@python/svgui@svgui/baseconfnode.xml
  • +0 -723
    tests/svgui/python@python/svgui@svgui/gui.svg
  • +0 -4
    tests/svgui/python@python/svgui@svgui/python.xml
  • +2 -0
    tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/baseconfnode.xml
  • +34 -0
    tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/hmi.wxg
  • +4 -0
    tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/py_ext.xml
  • +2 -0
    tests/wxGlade/python@py_ext/baseconfnode.xml
  • +4 -0
    tests/wxGlade/python@py_ext/py_ext.xml
  • +0 -2
    tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseconfnode.xml
  • +0 -34
    tests/wxGlade/python@python/HMIFrame@wxglade_hmi/hmi.wxg
  • +0 -4
    tests/wxGlade/python@python/HMIFrame@wxglade_hmi/python.xml
  • +0 -2
    tests/wxGlade/python@python/baseconfnode.xml
  • +0 -4
    tests/wxGlade/python@python/python.xml
  • --- 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 @@
    import os,sys,traceback
    import time
    -import confnodes
    +import features
    import types
    import shutil
    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 children
    def ConfNodePath(self):
    - return os.path.join(os.path.split(__file__)[0], "confnodes")
    + return os.path.split(__file__)[0]
    def CTNPath(self, CTNName=None):
    return self.ProjectPath
    @@ -1480,13 +1480,12 @@
    self.ResetIECProgramsAndVariables()
    # Generate C code and compilation params from confnode hierarchy
    - self.logger.write(_("Generating confnodes C code\n"))
    try:
    self.LocationCFilesAndCFLAGS, self.LDFLAGS, ExtraFiles = self._Generate_C(
    buildpath,
    self.PLCGeneratedLocatedVars)
    except Exception, exc:
    - 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())
    self.ResetBuildMD5()
    return False
    --- 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 @@
    havecanfestival = False
    try:
    - 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
    havecanfestival = True
    except:
    havecanfestival = False
    @@ -77,7 +77,7 @@
    #-------------------------------------------------------------------------------
    # CANFESTIVAL CONFNODE HACK
    #-------------------------------------------------------------------------------
    -# from confnodes.canfestival import canfestival
    +# from canfestival import canfestival
    # class LPC_canfestival_config:
    # def getCFLAGS(self, *args):
    # return ""
    --- /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 @@
    +*.pyc
    --- /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 @@
    +import keyword
    +
    +import wx
    +import wx.grid
    +import wx.stc as stc
    +import wx.lib.buttons
    +
    +from controls import CustomGrid, CustomTable, EditorPanel
    +
    +if wx.Platform == '__WXMSW__':
    + faces = { 'times': 'Times New Roman',
    + 'mono' : 'Courier New',
    + 'helv' : 'Arial',
    + 'other': 'Comic Sans MS',
    + 'size' : 10,
    + 'size2': 8,
    + }
    +else:
    + faces = { 'times': 'Times',
    + 'mono' : 'Courier',
    + 'helv' : 'Helvetica',
    + 'other': 'new century schoolbook',
    + 'size' : 12,
    + 'size2': 10,
    + }
    +
    +
    +def AppendMenu(parent, help, id, kind, text):
    + if wx.VERSION >= (2, 6, 0):
    + parent.Append(help=help, id=id, kind=kind, text=text)
    + else:
    + parent.Append(helpString=help, id=id, kind=kind, item=text)
    +
    +
    +[ID_CPPEDITOR,
    +] = [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):
    + old_length = len(old)
    + new_length = len(new)
    + common_length = min(old_length, new_length)
    + i = 0
    + for i in xrange(common_length):
    + if old[i] != new[i]:
    + break
    + if old_length < new_length:
    + if common_length > 0 and old[i] != new[i]:
    + return i + new_length - old_length
    + else:
    + 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]:
    + return i
    + else:
    + return i + 1
    + else:
    + return None
    +
    +class CppEditor(stc.StyledTextCtrl):
    +
    + fold_symbols = 3
    +
    + def __init__(self, parent, name, window, controler):
    + stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition,
    + wx.Size(0, 0), 0)
    +
    + 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.SetMargins(0,0)
    +
    + self.SetViewWhiteSpace(False)
    + #self.SetBufferedDraw(False)
    + #self.SetViewEOL(True)
    + #self.SetEOLMode(stc.STC_EOL_CRLF)
    + #self.SetUseAntiAliasing(True)
    +
    + self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
    + self.SetEdgeColumn(78)
    +
    + # 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())
    + self.RegisterImage(1,
    + wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
    + self.RegisterImage(2,
    + wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
    + self.RegisterImage(3,
    + wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
    +
    + # Indentation size
    + self.SetTabWidth(2)
    + self.SetUseTabs(0)
    +
    + self.Controler = controler
    + self.ParentWindow = window
    +
    + self.DisableEvents = True
    + self.Name = name
    + 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:
    + self.StartBuffering()
    + elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
    + self.Controler.EndBuffering()
    + self.StartBuffering()
    + self.CurrentAction = ("Add", event.GetPosition())
    + wx.CallAfter(self.RefreshModel)
    + elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
    + if self.CurrentAction == None:
    + self.StartBuffering()
    + elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
    + self.Controler.EndBuffering()
    + self.StartBuffering()
    + self.CurrentAction = ("Delete", event.GetPosition())
    + wx.CallAfter(self.RefreshModel)
    + event.Skip()
    +
    + def OnDoDrop(self, event):
    + self.ResetBuffer()
    + wx.CallAfter(self.RefreshModel)
    + event.Skip()
    +
    + # 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()
    +
    + def ResetBuffer(self):
    + if self.CurrentAction != None:
    + self.Controler.EndBuffering()
    + self.CurrentAction = None
    +
    + def RefreshView(self):
    + self.ResetBuffer()
    + self.DisableEvents = True
    + old_cursor_pos = self.GetCurrentPos()
    + old_text = self.GetText()
    + new_text = self.Controler.GetPartText(self.Name)
    + self.SetText(new_text)
    + new_cursor_pos = GetCursorPos(old_text, new_text)
    + if new_cursor_pos != None:
    + self.GotoPos(new_cursor_pos)
    + else:
    + self.GotoPos(old_cursor_pos)
    + self.ScrollToColumn(0)
    + self.EmptyUndoBuffer()
    + self.DisableEvents = False
    +
    + self.Colourise(0, -1)
    +
    + def DoGetBestSize(self):
    + return self.ParentWindow.GetPanelBestSize()
    +
    + def RefreshModel(self):
    + self.Controler.SetPartText(self.Name, self.GetText())
    +
    + def OnKeyPressed(self, event):
    + if self.CallTipActive():
    + self.CallTipCancel()
    + key = event.GetKeyCode()
    +
    + if key == 32 and event.ControlDown():
    + pos = self.GetCurrentPos()
    +
    + # Tips
    + if event.ShiftDown():
    + pass
    +## 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)')
    + # Code completion
    + else:
    + 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]))
    + else:
    + event.Skip()
    +
    + def OnKillFocus(self, event):
    + self.AutoCompCancel()
    + event.Skip()
    +
    + def OnUpdateUI(self, evt):
    + # check for matching braces
    + braceAtCaret = -1
    + braceOpposite = -1
    + charBefore = None
    + caretPos = self.GetCurrentPos()
    +
    + if caretPos > 0:
    + charBefore = self.GetCharAt(caretPos - 1)
    + styleBefore = self.GetStyleAt(caretPos - 1)
    +
    + # check before
    + if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
    + braceAtCaret = caretPos - 1
    +
    + # check after
    + if braceAtCaret < 0:
    + charAfter = self.GetCharAt(caretPos)
    + styleAfter = self.GetStyleAt(caretPos)
    +
    + if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
    + braceAtCaret = caretPos
    +
    + if braceAtCaret >= 0:
    + braceOpposite = self.BraceMatch(braceAtCaret)
    +
    + if braceAtCaret != -1 and braceOpposite == -1:
    + self.BraceBadLight(braceAtCaret)
    + else:
    + self.BraceHighlight(braceAtCaret, braceOpposite)
    + #pt = self.PointFromPosition(braceOpposite)
    + #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
    + #print pt
    + #self.Refresh(False)
    +
    +
    + def OnMarginClick(self, evt):
    + # fold and unfold as needed
    + if evt.GetMargin() == 2:
    + if evt.GetShift() and evt.GetControl():
    + self.FoldAll()
    + else:
    + lineClicked = self.LineFromPosition(evt.GetPosition())
    +
    + if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
    + if evt.GetShift():
    + self.SetFoldExpanded(lineClicked, True)
    + self.Expand(lineClicked, True, True, 1)
    + elif evt.GetControl():
    + if self.GetFoldExpanded(lineClicked):
    + self.SetFoldExpanded(lineClicked, False)
    + self.Expand(lineClicked, False, True, 0)
    + else:
    + self.SetFoldExpanded(lineClicked, True)
    + self.Expand(lineClicked, True, True, 100)
    + else:
    + self.ToggleFold(lineClicked)
    +
    +
    + def FoldAll(self):
    + lineCount = self.GetLineCount()
    + expanding = True
    +
    + # 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)
    + break
    +
    + lineNum = 0
    +
    + while lineNum < lineCount:
    + level = self.GetFoldLevel(lineNum)
    + if level & stc.STC_FOLDLEVELHEADERFLAG and \
    + (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
    +
    + if expanding:
    + self.SetFoldExpanded(lineNum, True)
    + lineNum = self.Expand(lineNum, True)
    + lineNum = lineNum - 1
    + else:
    + lastChild = self.GetLastChild(lineNum, -1)
    + self.SetFoldExpanded(lineNum, False)
    +
    + if lastChild > lineNum:
    + self.HideLines(lineNum+1, lastChild)
    +
    + lineNum = lineNum + 1
    +
    +
    +
    + def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
    + lastChild = self.GetLastChild(line, level)
    + line = line + 1
    +
    + while line <= lastChild:
    + if force:
    + if visLevels > 0:
    + self.ShowLines(line, line)
    + else:
    + self.HideLines(line, line)
    + else:
    + if doExpand:
    + self.ShowLines(line, line)
    +
    + if level == -1:
    + level = self.GetFoldLevel(line)
    +
    + if level & stc.STC_FOLDLEVELHEADERFLAG:
    + if force:
    + if visLevels > 1:
    + self.SetFoldExpanded(line, True)
    + else:
    + self.SetFoldExpanded(line, False)
    +
    + line = self.Expand(line, doExpand, force, visLevels-1)
    +
    + else:
    + if doExpand and self.GetFoldExpanded(line):
    + line = self.Expand(line, True, force, visLevels-1)
    + else:
    + line = self.Expand(line, False, force, visLevels-1)
    + else:
    + line = line + 1
    +
    + return line
    +
    + def Cut(self):
    + self.ResetBuffer()
    + self.DisableEvents = True
    + self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
    + self.DisableEvents = False
    + self.RefreshModel()
    + self.RefreshBuffer()
    +
    + def Copy(self):
    + self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
    +
    + def Paste(self):
    + self.ResetBuffer()
    + self.DisableEvents = True
    + self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
    + self.DisableEvents = False
    + self.RefreshModel()
    + self.RefreshBuffer()
    +
    +
    +#-------------------------------------------------------------------------------
    +# Helper for VariablesGrid values
    +#-------------------------------------------------------------------------------
    +
    +class VariablesTable(CustomTable):
    +
    + def GetValue(self, row, col):
    + if row < self.GetNumberRows():
    + if col == 0:
    + return row + 1
    + else:
    + 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.
    + """
    +
    + typelist = None
    + accesslist = None
    + for row in range(self.GetNumberRows()):
    + for col in range(self.GetNumberCols()):
    + editor = None
    + renderer = None
    + colname = self.GetColLabelValue(col, False)
    +
    + if colname == "Name":
    + editor = wx.grid.GridCellTextEditor()
    + elif colname == "Class":
    + editor = wx.grid.GridCellChoiceEditor()
    + editor.SetParameters("input,memory,output")
    + elif colname == "Type":
    + pass
    + else:
    + 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):
    + if id is not None:
    + event(self, id, function)
    + else:
    + event(self, 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)
    + else:
    + 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)
    +
    + self._init_sizers()
    +
    + 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())
    + self.RefreshModel()
    + self.RefreshView()
    + return new_row
    + setattr(self.VariablesGrid, "_AddRow", _AddVariable)
    +
    + def _DeleteVariable(row):
    + self.Table.RemoveRow(row)
    + self.RefreshModel()
    + self.RefreshView()
    + setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
    +
    + def _MoveVariable(row, move):
    + new_row = self.Table.MoveRow(row, move)
    + if new_row != row:
    + self.RefreshModel()
    + self.RefreshView()
    + return new_row
    + 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())
    + self.RefreshBuffer()
    +
    + # Buffer the last model state
    + def RefreshBuffer(self):
    + self.Controler.BufferCFile()
    + self.ParentWindow.RefreshTitle()
    + self.ParentWindow.RefreshFileMenu()
    + self.ParentWindow.RefreshEditMenu()
    + self.ParentWindow.RefreshPageTitles()
    +
    + def RefreshView(self):
    + 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):
    + self.RefreshModel()
    + wx.CallAfter(self.RefreshView)
    + event.Skip()
    +
    + 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():
    + new_id = wx.NewId()
    + 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):
    + new_id = wx.NewId()
    + 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())
    + type_menu.Destroy()
    + event.Veto()
    + else:
    + event.Skip()
    +
    + def GetVariableTypeFunction(self, base_type):
    + def VariableTypeFunction(event):
    + row = self.VariablesGrid.GetGridCursorRow()
    + self.Table.SetValueByName(row, "Type", base_type)
    + self.Table.ResetView(self.VariablesGrid)
    + self.RefreshModel()
    + self.RefreshView()
    + event.Skip()
    + return VariableTypeFunction
    +
    + def OnVariablesGridCellLeftClick(self, event):
    + if event.GetCol() == 0:
    + row = event.GetRow()
    + num = 0
    + if self.Table.GetValueByName(row, "Class") == "input":
    + dir = "%I"
    + for i in xrange(row):
    + if self.Table.GetValueByName(i, "Class") == "input":
    + num += 1
    + elif self.Table.GetValueByName(row, "Class") == "memory":
    + dir = "%M"
    + for i in xrange(row):
    + if self.Table.GetValueByName(i, "Class") == "memory":
    + num += 1
    + else:
    + dir = "%Q"
    + for i in xrange(row):
    + if self.Table.GetValueByName(i, "Class") == "output":
    + num += 1
    + 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()
    + event.Skip()
    +
    +
    +#-------------------------------------------------------------------------------
    +# SVGUIEditor Main Frame Class
    +#-------------------------------------------------------------------------------
    +
    +CFILE_PARTS = [
    + ("Includes", CppEditor),
    + ("Variables", VariablesEditor),
    + ("Globals", CppEditor),
    + ("Init", CppEditor),
    + ("CleanUp", CppEditor),
    + ("Retrieve", CppEditor),
    + ("Publish", CppEditor),
    +]
    +
    +#----------------------------------------------------------------------
    +# different icons for the collapsed/expanded states.
    +# Taken from standard Windows XP collapsed/expanded states.
    +#----------------------------------------------------------------------
    +
    +def GetCollapsedIconData():
    + return \
    +'\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():
    + import cStringIO
    + stream = cStringIO.StringIO(GetCollapsedIconData())
    + return wx.ImageFromStream(stream)
    +
    +#----------------------------------------------------------------------
    +def GetExpandedIconData():
    + return \
    +'\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\
    +`\x82'
    +
    +def GetExpandedIconBitmap():
    + return wx.BitmapFromImage(GetExpandedIconImage())
    +
    +def GetExpandedIconImage():
    + import cStringIO
    + 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 myDef and parDef:
    + if wx.Platform == "__WXMAC__":
    + brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
    + elif wx.Platform == "__WXMSW__":
    + if self.DoEraseBackground(dc):
    + brush = None
    + elif myDef and not parDef:
    + colBg = self.GetParent().GetBackgroundColour()
    + brush = wx.Brush(colBg, wx.SOLID)
    + return brush
    +
    + def DrawLabel(self, dc, width, height, dx=0, dy=0):
    + bmp = self.bmpLabel
    + if bmp is not None: # if the bitmap is used
    + if self.bmpDisabled and not self.IsEnabled():
    + bmp = self.bmpDisabled
    + if self.bmpFocus and self.hasFocus:
    + bmp = self.bmpFocus
    + if self.bmpSelected and not self.up:
    + bmp = self.bmpSelected
    + bw,bh = bmp.GetWidth(), bmp.GetHeight()
    + hasMask = bmp.GetMask() is not None
    + else:
    + bw = bh = 0 # no bitmap -> size is zero
    +
    + dc.SetFont(self.GetFont())
    + if self.IsEnabled():
    + dc.SetTextForeground(self.GetForegroundColour())
    + else:
    + dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
    +
    + label = self.GetLabel()
    + tw, th = dc.GetTextExtent(label) # size of text
    +
    + if bmp is not None:
    + 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.Panels = {}
    + 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_id = wx.NewId()
    + 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)
    + else:
    + panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
    + self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
    + panel.Hide()
    +
    + 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)))
    +
    + def __del__(self):
    + self.Controler.OnCloseEditor(self)
    +
    + def GetTitle(self):
    + fullname = self.Controler.CTNFullName()
    + if not self.Controler.CFileIsSaved():
    + return "~%s~" % fullname
    + return fullname
    +
    + def GetBufferState(self):
    + return self.Controler.GetBufferState()
    +
    + def Undo(self):
    + self.Controler.LoadPrevious()
    + self.RefreshView()
    +
    + def Redo(self):
    + self.Controler.LoadNext()
    + self.RefreshView()
    +
    + def HasNoModel(self):
    + return False
    +
    + def RefreshView(self):
    + for infos in self.Panels.itervalues():
    + infos["panel"].RefreshView()
    +
    + def GenPanelButtonCallback(self, name):
    + def PanelButtonCallback(event):
    + self.TogglePanel(name)
    + 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)
    + infos["panel"].Show()
    + 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)
    + infos["panel"].Hide()
    + self.MainSizer.RemoveGrowableRow(infos["row"])
    +
    + self.RefreshSizerLayout()
    +
    + def TogglePanel(self, name):
    + infos = self.Panels.get(name, None)
    + if infos is not None:
    + infos["expanded"] = not infos["expanded"]
    + infos["button"].SetToggle(infos["expanded"])
    + if infos["expanded"]:
    + infos["panel"].Show()
    + self.MainSizer.AddGrowableRow(infos["row"])
    + else:
    + infos["panel"].Hide()
    + self.MainSizer.RemoveGrowableRow(infos["row"])
    +
    + self.RefreshSizerLayout()
    +
    + def RefreshSizerLayout(self):
    + expand_spacer = True
    + for infos in self.Panels.itervalues():
    + expand_spacer = expand_spacer and not infos["expanded"]
    +
    + if self.SpacerExpanded != expand_spacer:
    + self.SpacerExpanded = expand_spacer
    + if expand_spacer:
    + self.Spacer.Show()
    + self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
    + else:
    + self.Spacer.Hide()
    + 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 @@
    +C extension
    \ 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 @@
    +from c_ext import *
    --- /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 @@
    +import wx
    +import os
    +from xml.dom import minidom
    +import cPickle
    +
    +from xmlclass import *
    +
    +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"}
    +
    +class _Cfile:
    + XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    + <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    + <xsd:element name="CExtension">
    + <xsd:complexType>
    + <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
    + <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/>
    + </xsd:complexType>
    + </xsd:element>
    + </xsd:schema>
    + """
    + EditorType = CFileEditor
    +
    + def __init__(self):
    + filepath = self.CFileName()
    +
    + self.CFile = CFileClasses["CFile"]()
    + if os.path.isfile(filepath):
    + xmlfile = open(filepath, 'r')
    + tree = minidom.parse(xmlfile)
    + xmlfile.close()
    +
    + for child in tree.childNodes:
    + if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
    + self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
    + self.CreateCFileBuffer(True)
    + else:
    + self.CreateCFileBuffer(False)
    + self.OnCTNSave()
    +
    + def CFileName(self):
    + 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([])
    + for var in variables:
    + variable = CFileClasses["variables_variable"]()
    + variable.setname(var["Name"])
    + variable.settype(var["Type"])
    + variable.setclass(var["Class"])
    + self.CFile.variables.appendvariable(variable)
    +
    + def GetVariables(self):
    + datas = []
    + for var in self.CFile.variables.getvariable():
    + datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
    + return datas
    +
    + def GetVariableLocationTree(self):
    + '''See ConfigTreeNode.GetVariableLocationTree() for a description.'''
    +
    + current_location = ".".join(map(str, self.GetCurrentLocation()))
    +
    + vars = []
    + input = memory = output = 0
    + for var in self.CFile.variables.getvariable():
    + var_size = self.GetSizeOfType(var.gettype())
    + var_location = ""
    + 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)
    + input += 1
    + 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)
    + memory += 1
    + else:
    + var_class = LOCATION_VAR_OUTPUT
    + if var_size is not None:
    + var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
    + output += 1
    + vars.append({"name": var.getname(),
    + "type": var_class,
    + "size": var_size,
    + "IEC_type": var.gettype(),
    + "var_name": var.getname(),
    + "location": var_location,
    + "description": "",
    + "children": []})
    +
    + return {"name": self.BaseParams.getName(),
    + "type": LOCATION_CONFNODE,
    + "location": self.GetFullIEC_Channel(),
    + "children": vars}
    +
    + def SetPartText(self, name, text):
    + if name == "Includes":
    + self.CFile.includes.settext(text)
    + elif name == "Globals":
    + self.CFile.globals.settext(text)
    + elif name == "Init":
    + 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):
    + if name == "Includes":
    + return self.CFile.includes.gettext()
    + elif name == "Globals":
    + return self.CFile.globals.gettext()
    + elif name == "Init":
    + 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()
    + return ""
    +
    + ConfNodeMethods = [
    + {"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()
    +
    + def OnCTNSave(self):
    + 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"))
    + xmlfile.close()
    +
    + self.MarkCFileAsSaved()
    + return True
    +
    + def CTNGenerate_C(self, buildpath, locations):
    + """
    + Generate C code
    + @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    + @param locations: List of complete variables locations \
    + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    + "NAME" : name of the variable (generally "__IW0_1_2" style)
    + "DIR" : direction "Q","I" or "M"
    + "SIZE" : size "X", "B", "W", "D", "L"
    + "LOC" : tuple of interger for IEC location (0,1,2,...)
    + }, ...]
    + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    + """
    + current_location = self.GetCurrentLocation()
    + # define a unique name for the generated C file
    + location_str = "_".join(map(str, current_location))
    +
    + text = "/* Code generated by Beremiz c_ext confnode */\n\n"
    +
    + # Adding includes
    + text += "/* User includes */\n"
    + text += self.CFile.includes.gettext()
    + text += "\n"
    +
    + text += """/* Beremiz c_ext confnode includes */
    +#ifdef _WINDOWS_H
    + #include "iec_types.h"
    +#else
    + #include "iec_std_lib.h"
    +#endif
    +
    +"""
    +
    + # Adding variables
    + vars = []
    + 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)
    + inputs += 1
    + elif variable.getclass() == "memory":
    + var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
    + memories += 1
    + else:
    + var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
    + outputs += 1
    + vars.append(var)
    + text += "/* Beremiz c_ext confnode user variables definition */\n"
    + base_types = self.GetCTRoot().GetBaseTypes()
    + for var in vars:
    + if var["Type"] in base_types:
    + prefix = "IEC_"
    + else:
    + prefix = ""
    + 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"
    + for var in vars:
    + text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
    + text += "\n"
    +
    + # 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 += " return 0;\n"
    + text += "\n}\n\n"
    +
    + text += "void __cleanup_%s(void)\n{\n"%location_str
    + text += self.CFile.cleanUpFunction.gettext()
    + text += "\n}\n\n"
    +
    + text += "void __retrieve_%s(void)\n{\n"%location_str
    + text += self.CFile.retrieveFunction.gettext()
    + text += "\n}\n\n"
    +
    + text += "void __publish_%s(void)\n{\n"%location_str
    + text += self.CFile.publishFunction.gettext()
    + text += "\n}\n\n"
    +
    + Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
    + cfile = open(Gen_Cfile_path,'w')
    + cfile.write(text)
    + cfile.close()
    +
    + 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
    + """
    + def Copy(self, model):
    + return cPickle.loads(cPickle.dumps(model))
    +
    + def CreateCFileBuffer(self, saved):
    + self.Buffering = False
    + self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
    +
    + def BufferCFile(self):
    + self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
    +
    + def StartBuffering(self):
    + self.Buffering = True
    +
    + def EndBuffering(self):
    + if self.Buffering:
    + self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
    + self.Buffering = False
    +
    + def MarkCFileAsSaved(self):
    + self.EndBuffering()
    + self.CFileBuffer.CurrentSaved()
    +
    + def CFileIsSaved(self):
    + return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
    +
    + def LoadPrevious(self):
    + self.EndBuffering()
    + self.CFile = cPickle.loads(self.CFileBuffer.Previous())
    +
    + def LoadNext(self):
    + 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
    +
    +class RootClass:
    +
    + CTNChildrenTypes = [("C_File",_Cfile, "C file")]
    +
    + def CTNGenerate_C(self, buildpath, locations):
    + return [],"",False
    +
    +
    --- /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:complexType>
    + <xsd:sequence>
    + <xsd:element name="includes" type="cext:CCode"/>
    + <xsd:element name="variables">
    + <xsd:complexType>
    + <xsd:sequence>
    + <xsd:element name="variable" minOccurs="0" maxOccurs="unbounded">
    + <xsd:complexType>
    + <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:simpleType>
    + <xsd:restriction base="xsd:string">
    + <xsd:enumeration value="input"/>
    + <xsd:enumeration value="memory"/>
    + <xsd:enumeration value="output"/>
    + </xsd:restriction>
    + </xsd:simpleType>
    + </xsd:attribute>
    + </xsd:complexType>
    + </xsd:element>
    + </xsd:sequence>
    + </xsd:complexType>
    + </xsd:element>
    + <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:sequence>
    + </xsd:complexType>
    + </xsd:element>
    + <xsd:complexType name="CCode">
    + <xsd:annotation>
    + <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
    + </xsd:annotation>
    + <xsd:sequence>
    + <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
    + </xsd:sequence>
    + </xsd:complexType>
    +</xsd:schema>
    --- /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 @@
    +*.pyc
    --- /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 @@
    +import os, sys
    +base_folder = os.path.split(sys.path[0])[0]
    +CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
    +
    +import wx
    +
    +from subindextable import EditingPanel
    +from networkedit import NetworkEditorTemplate
    +from controls import EditorPanel
    +
    +[ID_NETWORKEDITOR,
    +] = [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):
    +
    + ID = ID_NETWORKEDITOR
    +
    + 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)
    +
    + self._init_sizers()
    +
    + 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()
    +
    + def __del__(self):
    + 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))))
    + else:
    + 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):
    + pass
    +
    + def RefreshConfNodeMenu(self, confnode_menu):
    + confnode_menu.Enable(ID_NETWORKEDITORCONFNODEMENUMASTER, self.NetworkNodes.GetSelection() == 0)
    +
    + def GetTitle(self):
    + fullname = self.Controler.CTNFullName()
    + if not self.Manager.CurrentIsSaved():
    + return "~%s~" % fullname
    + return fullname
    +
    + def RefreshView(self):
    + 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 @@
    +CANOpen
    \ 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 @@
    +import os, sys
    +base_folder = os.path.split(sys.path[0])[0]
    +CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
    +
    +import wx
    +
    +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)))
    +
    + def __del__(self):
    + self.Controler.OnCloseEditor(self)
    +
    + def GetConfNodeMenuItems(self):
    + if self.Editable:
    + 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))))
    + else:
    + 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))]
    + return []
    +
    + def RefreshConfNodeMenu(self, confnode_menu):
    + confnode_menu.Enable(ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, False)
    +
    + def GetTitle(self):
    + fullname = self.Controler.CTNFullName()
    + if not self.Controler.CurrentIsSaved():
    + return "~%s~" % fullname
    + return fullname
    +
    + def RefreshView(self):
    + self.Editor.RefreshIndexList()
    +
    + def RefreshCurrentIndexList(self):
    + self.RefreshView()
    +
    + 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 @@
    +import os, sys
    +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
    +import wx
    +
    +from SlaveEditor import SlaveEditor
    +from NetworkEditor import NetworkEditor
    +
    +from gnosis.xml.pickle import *
    +from gnosis.xml.pickle.util import setParanoia
    +setParanoia(0)
    +
    +if wx.Platform == '__WXMSW__':
    + DEFAULT_SETTINGS = {
    + "CAN_Driver": "can_tcp_win32",
    + "CAN_Device": "127.0.0.1",
    + "CAN_Baudrate": "125K",
    + "Slave_NodeId": 2,
    + "Master_NodeId": 1,
    + }
    +else:
    + DEFAULT_SETTINGS = {
    + "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so",
    + "CAN_Device": "vcan0",
    + "CAN_Baudrate": "125K",
    + "Slave_NodeId": 2,
    + "Master_NodeId": 1,
    + }
    +
    +#--------------------------------------------------
    +# SLAVE
    +#--------------------------------------------------
    +
    +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:complexType>
    + <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:simpleType>
    + <xsd:restriction base="xsd:integer">
    + <xsd:minInclusive value="1"/>
    + <xsd:maxInclusive value="99"/>
    + </xsd:restriction>
    + </xsd:simpleType>
    + </xsd:attribute>
    + </xsd:complexType>
    + </xsd:element>
    + </xsd:schema>
    + """ % DEFAULT_SETTINGS
    +
    + EditorType = SlaveEditor
    +
    + def __init__(self):
    + # TODO change netname when name change
    + NodeManager.__init__(self)
    + odfilepath = self.GetSlaveODPath()
    + if(os.path.isfile(odfilepath)):
    + self.OpenFileInCurrent(odfilepath)
    + else:
    + self.FilePath = ""
    + 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
    + "slave", # Type
    + description,# description
    + profile, # profile
    + filepath, # prfile filepath
    + NMT, # NMT
    + options) # options
    + else:
    + self.CreateNewNode("SlaveNode", # Name - will be changed at build time
    + 0x00, # NodeID - will be changed at build time
    + "slave", # Type
    + "", # description
    + "None", # profile
    + "", # prfile filepath
    + "heartbeat", # NMT
    + []) # options
    + dialog.Destroy()
    + self.OnCTNSave()
    +
    + def GetSlaveODPath(self):
    + return os.path.join(self.CTNPath(), 'slave.od')
    +
    + def GetCanDevice(self):
    + return self.CanFestivalSlaveNode.getCan_Device()
    +
    + def _OpenView(self):
    + ConfigTreeNode._OpenView(self)
    + if self._View is not None:
    + self._View.SetBusId(self.GetCurrentLocation())
    +
    + ConfNodeMethods = [
    + {"bitmap" : os.path.join("images", "NetworkEdit"),
    + "name" : "Edit slave",
    + "tooltip" : "Edit CanOpen slave with ObjdictEdit",
    + "method" : "_OpenView"},
    + ]
    +
    + def OnCTNClose(self):
    + if self._View:
    + self._View.Close()
    +
    + def CTNTestModified(self):
    + return self.ChangesToSave or self.OneFileHasChanged()
    +
    + def OnCTNSave(self):
    + 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())
    +
    + return result
    +
    + def CTNGenerate_C(self, buildpath, locations):
    + """
    + Generate C code
    + @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    + @param locations: List of complete variables locations \
    + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    + "NAME" : name of the variable (generally "__IW0_1_2" style)
    + "DIR" : direction "Q","I" or "M"
    + "SIZE" : size "X", "B", "W", "D", "L"
    + "LOC" : tuple of interger for IEC location (0,1,2,...)
    + }, ...]
    + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    + """
    + current_location = self.GetCurrentLocation()
    + # define a unique name for the generated C file
    + 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)
    + if res :
    + raise Exception, res
    + res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
    + if res :
    + raise Exception, res
    + return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
    +
    + def LoadPrevious(self):
    + self.LoadCurrentPrevious()
    +
    + def LoadNext(self):
    + self.LoadCurrentNext()
    +
    + def GetBufferState(self):
    + return self.GetCurrentBufferState()
    +
    +#--------------------------------------------------
    +# MASTER
    +#--------------------------------------------------
    +
    +class MiniNodeManager(NodeManager):
    +
    + def __init__(self, parent, filepath, fullname):
    + NodeManager.__init__(self)
    +
    + self.OpenFileInCurrent(filepath)
    +
    + self.Parent = parent
    + self.Fullname = fullname
    +
    + def OnCloseEditor(self, view):
    + self.Parent.OnCloseEditor(view)
    +
    + def CTNFullName(self):
    + return self.Fullname
    +
    + 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:complexType>
    + <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"/>
    + </xsd:complexType>
    + </xsd:element>
    + </xsd:schema>
    + """ % DEFAULT_SETTINGS
    +
    + EditorType = NetworkEditor
    +
    + def __init__(self):
    + 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)
    +
    + return result
    +
    + def _OpenView(self):
    + ConfigTreeNode._OpenView(self)
    + if self._View is not None:
    + self._View.SetBusId(self.GetCurrentLocation())
    +
    + _GeneratedView = None
    + 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"))
    + return
    +
    + masterpath = os.path.join(buildpath, "MasterGenerated.od")
    + if not os.path.exists(masterpath):
    + self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
    + return
    +
    + 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)
    +
    + ConfNodeMethods = [
    + {"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
    +
    + def OnCTNClose(self):
    + ConfigTreeNode.OnCTNClose(self)
    + self._CloseGenerateView()
    + return True
    +
    + def CTNTestModified(self):
    + return self.ChangesToSave or self.HasChanged()
    +
    + def OnCTNSave(self):
    + self.SetRoot(self.CTNPath())
    + return self.SaveProject() is None
    +
    + def CTNGenerate_C(self, buildpath, locations):
    + """
    + Generate C code
    + @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    + @param locations: List of complete variables locations \
    + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    + "NAME" : name of the variable (generally "__IW0_1_2" style)
    + "DIR" : direction "Q","I" or "M"
    + "SIZE" : size "X", "B", "W", "D", "L"
    + "LOC" : tuple of interger for IEC location (0,1,2,...)
    + }, ...]
    + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    + """
    + 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
    + try:
    + 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
    + # Do generate C file.
    + res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
    + if res :
    + raise Exception, res
    +
    + file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
    + dump(master, file)
    + file.close()
    +
    + return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
    +
    + def LoadPrevious(self):
    + self.Manager.LoadCurrentPrevious()
    +
    + def LoadNext(self):
    + self.Manager.LoadCurrentNext()
    +
    + def GetBufferState(self):
    + return self.Manager.GetCurrentBufferState()
    +
    +class RootClass:
    + XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    + <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    + <xsd:element name="CanFestivalInstance">
    + <xsd:complexType>
    + <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"/>
    + </xsd:complexType>
    + </xsd:element>
    + </xsd:schema>
    + """ % DEFAULT_SETTINGS
    +
    + CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"),
    + ("CanOpenSlave",_SlaveCTN, "CanOpen Slave")]
    + def GetParamsAttributes(self, path = None):
    + infos = ConfigTreeNode.GetParamsAttributes(self, path = None)
    + for element in infos:
    + 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
    + return infos
    +
    + 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'
    + else:
    + can_driver += '.dll'
    + return can_driver
    +
    + def CTNGenerate_C(self, buildpath, locations):
    +
    + format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
    + "candriver" : self.GetCanDriver(),
    + "nodes_includes" : "",
    + "board_decls" : "",
    + "nodes_init" : "",
    + "nodes_open" : "",
    + "nodes_stop" : "",
    + "nodes_close" : "",
    + "nodes_send_sync" : "",
    + "nodes_proceed_sync" : "",
    + "slavebootups" : "",
    + "slavebootup_register" : "",
    + "post_sync" : "",
    + "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)
    + if child_data is None:
    + # Not a slave -> master
    + child_data = getattr(child, "CanFestivalNode")
    + # Apply sync setting
    + format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n '%(
    + nodename,
    + 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()
    + if len(SlaveIDs) == 0:
    + # define post_SlaveBootup lookup functions
    + format_dict["slavebootups"] += (
    + "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
    + else:
    + for id in SlaveIDs:
    + 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)+
    + " switch(nodeId){\n")
    + # one case per declared node, mark node as booted
    + for id in SlaveIDs:
    + format_dict["slavebootups"] += (
    + " case %d:\n"%(id)+
    + " %s_slave_%d_booted = 1;\n"%(nodename, id)+
    + " break;\n")
    + format_dict["slavebootups"] += (
    + " default:\n"+
    + " break;\n"+
    + " }\n"+
    + " if( ")
    + # 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"+
    + "}\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))
    + else:
    + # Slave node
    + align = child_data.getSync_Align()
    + align_ratio=child_data.getSync_Align_Ratio()
    + if align > 0:
    + 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(-1);\n"+
    + " }else{\n"+
    + " align_tick(%d);\n"%(align_ratio)+
    + " }\n"+
    + "}\n")
    + 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 '%(
    + nodename,
    + 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'%(
    + nodename,
    + child.GetCanDevice(),
    + 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')
    + f.write(cf_main)
    + f.close()
    +
    + 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*/
    +%(nodes_includes)s
    +
    +#define BOARD_DECL(nodename, busname, baudrate)\
    + s_BOARD nodename##Board = {busname, baudrate};
    +
    +/* CAN channels declaration */
    +%(board_decls)s
    +
    +/* 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 */
    +%(slavebootups)s
    +
    +/* One slave node post_sync callback.
    + * Used to align PLC tick-time on CANopen SYNC
    + */
    +%(post_sync)s
    +
    +#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);\
    + /* init */\
    + 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
    + %(post_sync_register)s
    + %(nodes_init)s
    +}
    +
    +#define NODE_STOP(nodename) \
    + if(init_level-- > 0)\
    + {\
    + masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\
    + setState(&nodename##_Data, Stopped);\
    + }
    +
    +void Exit(CO_Data* d, UNS32 id)
    +{
    + %(nodes_stop)s
    +}
    +
    +#define NODE_CLOSE(nodename) \
    + if(init_level_c-- > 0)\
    + {\
    + canClose(&nodename##_Data);\
    + }
    +
    +void __cleanup_%(locstr)s(void)
    +{
    + // Stop timer thread
    + if(init_level-- > 0){
    + int init_level_c = init_level;
    + StopTimerLoop(&Exit);
    + %(nodes_close)s
    + }
    +
    + TimerCleanup();
    +}
    +
    +#ifndef stderr
    +#define fprintf(...)
    +#define fflush(...)
    +#endif
    +
    +#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);\
    + fflush(stderr);\
    + return -1;\
    + }\
    + init_level++;
    +
    +/*************************** 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");\
    + fflush(stderr);\
    + return -1;\
    + }
    +#endif
    +
    + TimerInit();
    +
    + %(nodes_open)s
    +
    + // Start timer thread
    + StartTimerLoop(&InitNodes);
    + init_level++;
    + return 0;
    +}
    +
    +#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
    + * */
    + EnterMutex();
    + /* Send Sync */
    + %(nodes_send_sync)s
    +}
    +
    +#define NODE_PROCEED_SYNC(nodename)\
    + proceedSYNC(&nodename##_Data);
    +
    +void __publish_%(locstr)s(void)
    +{
    + /* Process sync event */
    + %(nodes_proceed_sync)s
    + LeaveMutex();
    +}
    +
    --- /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 @@
    +#!/usr/bin/env python
    +# -*- coding: utf-8 -*-
    +
    +#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
    +
    +from types import *
    +
    +# 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
    +RPDO = 1
    +TPDO = 2
    +
    +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):
    + pass
    +
    +
    +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)]
    + list_car.reverse()
    + 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 node: 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 = []
    + if type & RPDO:
    + indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
    + if type & TPDO:
    + indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF])
    + if not parameters:
    + return [idx + 0x200 for idx in indexes]
    + else:
    + return indexes
    +
    +
    +def SearchNodePDOMapping(loc_infos, node):
    + """
    + Find the PDO indexes of a node
    + @param node: 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)
    + if values != None:
    + for subindex, mapping in enumerate(values):
    + if subindex != 0 and mapping & 0xFFFFFF00 == model:
    + return PDOidx, subindex
    + return None
    +
    +
    +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)
    + # Re-Enable PDO
    + # ---- 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)
    + nbparams = 3
    + 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)
    + nbparams += 1
    + # Map Variables
    + 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)
    + nbparams += 1
    + return dcfdata, nbparams
    +
    +class ConciseDCFGenerator:
    +
    + def __init__(self, nodelist, nodename):
    + # Dictionary of location informations classed by name
    + self.IECLocations = {}
    + # 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
    + @param node: node
    + @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
    + if pdo_cobid > 0x600 :
    + 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"]
    + node.SetNodeID(nodeid)
    +
    + RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
    +
    + # Get Slave's default SDO server parameters
    + RSDO_cobid = node.GetEntry(0x1200,0x01)
    + if not RSDO_cobid:
    + RSDO_cobid = 0x600 + nodeid
    + TSDO_cobid = node.GetEntry(0x1200,0x02)
    + if not TSDO_cobid:
    + 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):
    + """
    + Return MasterNode.
    + """
    + return self.MasterNode
    +
    + 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]]
    + tmpnbparams.reverse()
    + nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
    + data = nodeDCF[4:] + data
    +
    + # Build new DCF
    + 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]
    + else:
    + index = start_index
    +
    + # 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 cobid == 0:
    + if len(self.ListCobIDAvailable) == 0:
    + return None
    + # 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]
    + index += 1
    + return None
    +
    + 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
    + if sync_TPDOs:
    + return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
    + else:
    + return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
    + return 0, ""
    +
    + 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
    + else:
    + # 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)
    + elif len(loc) == 2:
    + continue
    +
    + 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)
    +
    + # Get the entry info
    + subentry_infos = node.GetSubentryInfos(index, subindex)
    +
    + # If a PDO mappable
    + if subentry_infos and subentry_infos["pdo"]:
    + if sizelocation == "X" and len(loc) > 3:
    + numbit = 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)
    + else:
    + numbit = None
    +
    + 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}
    + else:
    + 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)
    + if result != None:
    + 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:
    + if sync_TPDOs:
    + # Change TransmitType to SYNCHRONE
    + data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, [])
    + else:
    + # 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)
    +
    + mapping = [None]
    + values = node.GetEntry(index)
    + # Store the size of each entry mapped in PDO
    + for value in values[1:]:
    + if value != 0:
    + 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)
    + else:
    + self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
    +
    + else:
    + # 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
    + nbparams = 0
    + dataparams = ""
    +
    + # Generate the best PDO mapping for each type of PDO
    + for pdotype in (TPDO, RPDO):
    + if len(locations[pdotype]) > 0:
    + pdosize = 0
    + pdomapping = []
    + result = self.GetEmptyPDO(nodeid, pdotype)
    + if result is None:
    + 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)
    + dataparams += data
    + nbparams += nbaddedparams
    + pdosize = loc_infos["size"]
    + pdomapping = [(name, loc_infos)]
    + result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
    + if result is None:
    + raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
    + pdoindex, pdocobid, pdonbparams = result
    + else:
    + 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)
    + dataparams += data
    + 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:
    + current_idx = idx
    +
    + # 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
    + if sync_TPDOs:
    + self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
    + else:
    + self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
    +
    + mapping = []
    + for item in pdo_infos["mapping"]:
    + if isinstance(item, ListType):
    + mapping.extend(item)
    + else:
    + mapping.append(item)
    +
    + # Add some subentries to PDO mapping if there is not enough
    + if len(mapping) > 1:
    + self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
    +
    + # Generate MasterNode's PDO mapping
    + for subindex, variable in enumerate(mapping):
    + if subindex == 0:
    + continue
    + new_index = False
    +
    + if isinstance(variable, (IntType, LongType)):
    + # If variable is an integer then variable is unexpected
    + self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
    + else:
    + 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"]
    +
    + # Generate entry name
    + 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:
    + # Entry doesn't exist
    + if not self.MasterNode.IsEntry(mapvariableidx):
    + # Add entry to MasterNode
    + self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
    + new_index = True
    + nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
    + else:
    + # 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
    + else:
    + break
    +
    + # 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
    + else:
    + subindexname = "%(index)d_%(subindex)d"%variable_infos
    + # If entry have just been created, no subentry have to be added
    + if not new_index:
    + self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode)
    + nbsubentries += 1
    + # 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)
    + if typeinfos != None:
    + 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):
    + IECLocations = {}
    + pointers = {}
    + 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
    + else:
    + # 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)
    + elif len(loc) != 2:
    + continue
    +
    + # 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)
    +
    + # Get the entry info
    + 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
    + return pointers
    +
    +if __name__ == "__main__":
    + import os, sys, getopt
    +
    + def usage():
    + print """
    +Usage of config_utils.py test :
    +
    + %s [options]
    +
    +Options:
    + --help (-h)
    + Displays help informations for config_utils
    +
    + --reset (-r)
    + Reset the reference result of config_utils test.
    + Use with caution. Be sure that config_utils
    + is currently working properly.
    +"""%sys.argv[0]
    +
    + # Boolean that indicate if reference result must be redefined
    + reset = False
    +
    + # Extract command options
    + try:
    + opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"])
    + except getopt.GetoptError:
    + # print help information and exit:
    + usage()
    + sys.exit(2)
    +
    + # Test each option
    + for o, a in opts:
    + if o in ("-h", "--help"):
    + usage()
    + sys.exit()
    + elif o in ("-r", "--reset"):
    + reset = True
    +
    + # Extract workspace base folder
    + base_folder = sys.path[0]
    + for i in xrange(3):
    + 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 *
    + from nodelist 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
    + try:
    + masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
    + except ValueError, message:
    + print "%s\nTest Failed!"%message
    + sys.exit()
    +
    + import pprint
    + # 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
    + if reset:
    + # Write Text into reference result file
    + testfile = open("test_config/result.txt", "w")
    + testfile.write(result)
    + testfile.close()
    +
    + print "Reset Successful!"
    + else:
    + import os
    +
    + testfile = open("test_config/result_tmp.txt", "w")
    + testfile.write(result)
    + testfile.close()
    +
    + 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 @@
    +[FileInfo]
    +CreatedBy=ESAcademy
    +ModifiedBy=ESAcademy
    +Description=PEAK MicroMod CANopenIA Generic
    +CreationTime=09:41PM
    +CreationDate=05-05-2003
    +ModificationTime=05:05PM
    +ModificationDate=03-23-2005
    +FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds
    +FileVersion=1
    +FileRevision=1
    +EDSVersion=4
    +
    +[DeviceInfo]
    +VendorName=PEAK System Technik
    +VendorNumber=0x00000175
    +ProductName=PEAK MicroMod CANopenIA Generic
    +ProductNumber=0x00100000
    +RevisionNumber=0x00010001
    +OrderCode=na
    +BaudRate_10=0
    +BaudRate_20=0
    +BaudRate_50=1
    +BaudRate_125=1
    +BaudRate_250=1
    +BaudRate_500=1
    +BaudRate_800=1
    +BaudRate_1000=1
    +SimpleBootUpMaster=0
    +SimpleBootUpSlave=1
    +Granularity=0
    +DynamicChannelsSupported=0
    +CompactPDO=0
    +GroupMessaging=0
    +NrOfRXPDO=4
    +NrOfTXPDO=4
    +LSS_Supported=0
    +
    +[DummyUsage]
    +Dummy0001=0
    +Dummy0002=0
    +Dummy0003=0
    +Dummy0004=0
    +Dummy0005=1
    +Dummy0006=1
    +Dummy0007=1
    +
    +[Comments]
    +Lines=0
    +
    +[MandatoryObjects]
    +SupportedObjects=3
    +1=0x1000
    +2=0x1001
    +3=0x1018
    +
    +[1000]
    +ParameterName=Device Type
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=ro
    +DefaultValue=0x000F0191
    +PDOMapping=0
    +
    +[1001]
    +ParameterName=Error Register
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1018]
    +ParameterName=Identity Object
    +ObjectType=0x9
    +SubNumber=4
    +
    +[1018sub0]
    +ParameterName=number of entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=3
    +PDOMapping=0
    +
    +[1018sub1]
    +ParameterName=Vendor ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=ro
    +DefaultValue=0x00000175
    +PDOMapping=0
    +
    +[1018sub2]
    +ParameterName=Product Code
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=ro
    +DefaultValue=0x00100000
    +PDOMapping=0
    +
    +[1018sub3]
    +ParameterName=Revision number
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=ro
    +DefaultValue=0x00010001
    +PDOMapping=0
    +
    +[OptionalObjects]
    +SupportedObjects=41
    +1=0x1002
    +2=0x1005
    +3=0x1008
    +4=0x1009
    +5=0x100A
    +6=0x100C
    +7=0x100D
    +8=0x1010
    +9=0x1011
    +10=0x1016
    +11=0x1017
    +12=0x1020
    +13=0x1400
    +14=0x1401
    +15=0x1402
    +16=0x1403
    +17=0x1600
    +18=0x1601
    +19=0x1602
    +20=0x1603
    +21=0x1800
    +22=0x1801
    +23=0x1802
    +24=0x1803
    +25=0x1A00
    +26=0x1A01
    +27=0x1A02
    +28=0x1A03
    +29=0x1F50
    +30=0x6000
    +31=0x6002
    +32=0x6200
    +33=0x6202
    +34=0x6206
    +35=0x6207
    +36=0x6401
    +37=0x6411
    +38=0x6423
    +39=0x6426
    +40=0x6443
    +41=0x6444
    +
    +[1002]
    +ParameterName=PEAK Status Register
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=ro
    +PDOMapping=0
    +
    +[1005]
    +ParameterName=COB-ID SYNC
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x00000080
    +PDOMapping=0
    +
    +[1008]
    +ParameterName=Manufacturer Device Name
    +ObjectType=0x7
    +DataType=0x0009
    +AccessType=const
    +PDOMapping=0
    +
    +[1009]
    +ParameterName=Manufacturer Hardware Version
    +ObjectType=0x7
    +DataType=0x0009
    +AccessType=const
    +PDOMapping=0
    +
    +[100a]
    +ParameterName=Manufacturer Software Version
    +ObjectType=0x7
    +DataType=0x0009
    +AccessType=const
    +PDOMapping=0
    +
    +[100c]
    +ParameterName=Guard Time
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[100d]
    +ParameterName=Life Time Factor
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0x00
    +PDOMapping=0
    +
    +[1010]
    +ParameterName=Store Parameter Field
    +ObjectType=0x8
    +SubNumber=2
    +
    +[1010sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[1010sub1]
    +ParameterName=Save all Parameters
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +PDOMapping=0
    +
    +[1011]
    +ParameterName=Restore Default Parameters
    +ObjectType=0x8
    +SubNumber=2
    +
    +[1011sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[1011sub1]
    +ParameterName=Restore all Default Parameters
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +PDOMapping=0
    +
    +[1016]
    +ParameterName=Consumer Heartbeat Time
    +ObjectType=0x8
    +SubNumber=4
    +
    +[1016sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=3
    +PDOMapping=0
    +LowLimit=0x1
    +
    +[1016sub1]
    +ParameterName=Consumer Heartbeat Time
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1016sub2]
    +ParameterName=Consumer Heartbeat Time
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1016sub3]
    +ParameterName=Consumer Heartbeat Time
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1017]
    +ParameterName=Producer Heartbeat Time
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1020]
    +ParameterName=Verify Configuration
    +ObjectType=0x8
    +SubNumber=3
    +
    +[1020sub0]
    +ParameterName=Number of entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=2
    +PDOMapping=0
    +
    +[1020sub1]
    +ParameterName=Configuration date
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +PDOMapping=0
    +
    +[1020sub2]
    +ParameterName=Configuration time
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +PDOMapping=0
    +
    +[1400]
    +ParameterName=Receive PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=3
    +
    +[1400sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=2
    +PDOMapping=0
    +
    +[1400sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x200
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1400sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1401]
    +ParameterName=Receive PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=3
    +
    +[1401sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=2
    +PDOMapping=0
    +
    +[1401sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x300
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1401sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1402]
    +ParameterName=Receive PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=3
    +
    +[1402sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=2
    +PDOMapping=0
    +LowLimit=0x02
    +HighLimit=0x05
    +
    +[1402sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x80000400
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1402sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1403]
    +ParameterName=Receive PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=3
    +
    +[1403sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=2
    +PDOMapping=0
    +LowLimit=0x02
    +HighLimit=0x05
    +
    +[1403sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x80000500
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1403sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1600]
    +ParameterName=Receive PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=2
    +
    +[1600sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=1
    +PDOMapping=0
    +
    +[1600sub1]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x62000108
    +PDOMapping=0
    +
    +[1601]
    +ParameterName=Receive PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=5
    +
    +[1601sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=4
    +PDOMapping=0
    +
    +[1601sub1]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64110110
    +PDOMapping=0
    +
    +[1601sub2]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64110210
    +PDOMapping=0
    +
    +[1601sub3]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64110310
    +PDOMapping=0
    +
    +[1601sub4]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64110410
    +PDOMapping=0
    +
    +[1602]
    +ParameterName=Receive PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=1
    +
    +[1602sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1603]
    +ParameterName=Receive PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=1
    +
    +[1603sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1800]
    +ParameterName=Transmit PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=5
    +
    +[1800sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=5
    +PDOMapping=0
    +LowLimit=0x02
    +HighLimit=0x05
    +
    +[1800sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x180
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1800sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1800sub3]
    +ParameterName=Inhibit Time
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0x0000
    +PDOMapping=0
    +
    +[1800sub5]
    +ParameterName=Event Timer
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1801]
    +ParameterName=Transmit PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=5
    +
    +[1801sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=5
    +PDOMapping=0
    +LowLimit=0x02
    +HighLimit=0x05
    +
    +[1801sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x280
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1801sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1801sub3]
    +ParameterName=Inhibit Time
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0x0000
    +PDOMapping=0
    +
    +[1801sub5]
    +ParameterName=Event Timer
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1802]
    +ParameterName=Transmit PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=5
    +
    +[1802sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=5
    +PDOMapping=0
    +LowLimit=0x02
    +HighLimit=0x05
    +
    +[1802sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x380
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1802sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1802sub3]
    +ParameterName=Inhibit Time
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0x0000
    +PDOMapping=0
    +
    +[1802sub5]
    +ParameterName=Event Timer
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1803]
    +ParameterName=Transmit PDO Communication Parameter
    +ObjectType=0x9
    +SubNumber=5
    +
    +[1803sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=5
    +PDOMapping=0
    +LowLimit=0x02
    +HighLimit=0x05
    +
    +[1803sub1]
    +ParameterName=COB-ID
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=$NODEID+0x80000480
    +PDOMapping=0
    +LowLimit=0x00000001
    +HighLimit=0xFFFFFFFF
    +
    +[1803sub2]
    +ParameterName=Transmission Type
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=255
    +PDOMapping=0
    +
    +[1803sub3]
    +ParameterName=Inhibit Time
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0x0000
    +PDOMapping=0
    +
    +[1803sub5]
    +ParameterName=Event Timer
    +ObjectType=0x7
    +DataType=0x0006
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1a00]
    +ParameterName=Transmit PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=2
    +
    +[1a00sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=1
    +PDOMapping=0
    +
    +[1a00sub1]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x60000108
    +PDOMapping=0
    +
    +[1a01]
    +ParameterName=Transmit PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=5
    +
    +[1a01sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=4
    +PDOMapping=0
    +
    +[1a01sub1]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010110
    +PDOMapping=0
    +
    +[1a01sub2]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010210
    +PDOMapping=0
    +
    +[1a01sub3]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010310
    +PDOMapping=0
    +
    +[1a01sub4]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010410
    +PDOMapping=0
    +
    +[1a02]
    +ParameterName=Transmit PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=5
    +
    +[1a02sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=4
    +PDOMapping=0
    +
    +[1a02sub1]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010510
    +PDOMapping=0
    +
    +[1a02sub2]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010610
    +PDOMapping=0
    +
    +[1a02sub3]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010710
    +PDOMapping=0
    +
    +[1a02sub4]
    +ParameterName=PDO Mapping Entry
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0x64010810
    +PDOMapping=0
    +
    +[1a03]
    +ParameterName=Transmit PDO Mapping Parameter
    +ObjectType=0x9
    +SubNumber=1
    +
    +[1a03sub0]
    +ParameterName=Number of Entries
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[1f50]
    +ParameterName=Download Program Data
    +ObjectType=0x8
    +SubNumber=2
    +
    +[1f50sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=3
    +PDOMapping=0
    +
    +[1f50sub3]
    +ParameterName=Download Program Data - HW Settings
    +ObjectType=0x7
    +DataType=0x000F
    +AccessType=rw
    +PDOMapping=0
    +
    +[6000]
    +ParameterName=Read Digital Input 8-bit
    +ObjectType=0x8
    +SubNumber=2
    +
    +[6000sub0]
    +ParameterName=Number of Elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[6000sub1]
    +ParameterName=DigInput8_1
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +PDOMapping=1
    +
    +[6002]
    +ParameterName=Polarity Digital Input
    +ObjectType=0x8
    +SubNumber=2
    +
    +[6002sub0]
    +ParameterName=Number of Elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[6002sub1]
    +ParameterName=Polarity8_1
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6200]
    +ParameterName=Write Digital Output 8-bit
    +ObjectType=0x8
    +SubNumber=2
    +
    +[6200sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[6200sub1]
    +ParameterName=DigOutput8_1
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rww
    +PDOMapping=1
    +
    +[6202]
    +ParameterName=Polarity Digital Output
    +ObjectType=0x8
    +SubNumber=2
    +
    +[6202sub0]
    +ParameterName=Number of Elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[6202sub1]
    +ParameterName=Polarity8_1
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6206]
    +ParameterName=Error Mode Digital Output
    +ObjectType=0x8
    +SubNumber=2
    +
    +[6206sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[6206sub1]
    +ParameterName=Error Mode 1
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6207]
    +ParameterName=Error Value Digital Output
    +ObjectType=0x8
    +SubNumber=2
    +
    +[6207sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=1
    +PDOMapping=0
    +
    +[6207sub1]
    +ParameterName=Error Value 1
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6401]
    +ParameterName=Read Analog Input 16-bit
    +ObjectType=0x8
    +SubNumber=9
    +
    +[6401sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=8
    +PDOMapping=0
    +
    +[6401sub1]
    +ParameterName=AnalogInput16_1
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6401sub2]
    +ParameterName=AnalogInput16_2
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6401sub3]
    +ParameterName=AnalogInput16_3
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6401sub4]
    +ParameterName=AnalogInput16_4
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6401sub5]
    +ParameterName=AnalogInput16_5
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6401sub6]
    +ParameterName=AnalogInput16_6
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6401sub7]
    +ParameterName=AnalogInput16_7
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6401sub8]
    +ParameterName=AnalogInput16_8
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=ro
    +PDOMapping=1
    +
    +[6411]
    +ParameterName=Write Analog Output 16-bit
    +ObjectType=0x8
    +SubNumber=5
    +
    +[6411sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=4
    +PDOMapping=0
    +
    +[6411sub1]
    +ParameterName=AnalogOutput16_1
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=rww
    +PDOMapping=1
    +
    +[6411sub2]
    +ParameterName=AnalogOutput16_2
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=rww
    +PDOMapping=1
    +
    +[6411sub3]
    +ParameterName=AnalogOutput16_3
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=rww
    +PDOMapping=1
    +
    +[6411sub4]
    +ParameterName=AnalogOutput16_4
    +ObjectType=0x7
    +DataType=0x0003
    +AccessType=rww
    +PDOMapping=1
    +
    +[6423]
    +ParameterName=Analog Input Global Interrupt
    +ObjectType=0x7
    +DataType=0x0001
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426]
    +ParameterName=Analog Input Interrupt Delta
    +ObjectType=0x8
    +SubNumber=9
    +
    +[6426sub0]
    +ParameterName=NrOfObjects
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=8
    +PDOMapping=0
    +
    +[6426sub1]
    +ParameterName=Analog Input Delta 1
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426sub2]
    +ParameterName=Analog Input Delta 2
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426sub3]
    +ParameterName=Analog Input Delta 3
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426sub4]
    +ParameterName=Analog Input Delta 4
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426sub5]
    +ParameterName=Analog Input Delta 5
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426sub6]
    +ParameterName=Analog Input Delta 6
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426sub7]
    +ParameterName=Analog Input Delta 7
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6426sub8]
    +ParameterName=Analog Input Delta 8
    +ObjectType=0x7
    +DataType=0x0007
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6443]
    +ParameterName=Error Mode Analog Output
    +ObjectType=0x8
    +SubNumber=5
    +
    +[6443sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=4
    +PDOMapping=0
    +
    +[6443sub1]
    +ParameterName=Error Mode 1
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6443sub2]
    +ParameterName=Error Mode 2
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6443sub3]
    +ParameterName=Error Mode 3
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6443sub4]
    +ParameterName=Error Mode 4
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6444]
    +ParameterName=Error Value Analog Output
    +ObjectType=0x8
    +SubNumber=5
    +
    +[6444sub0]
    +ParameterName=Number of elements
    +ObjectType=0x7
    +DataType=0x0005
    +AccessType=ro
    +DefaultValue=4
    +PDOMapping=0
    +
    +[6444sub1]
    +ParameterName=Error Value 1
    +ObjectType=0x7
    +DataType=0x0004
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6444sub2]
    +ParameterName=Error Value 2
    +ObjectType=0x7
    +DataType=0x0004
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6444sub3]
    +ParameterName=Error Value 3
    +ObjectType=0x7
    +DataType=0x0004
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[6444sub4]
    +ParameterName=Error Value 4
    +ObjectType=0x7
    +DataType=0x0004
    +AccessType=rw
    +DefaultValue=0
    +PDOMapping=0
    +
    +[ManufacturerObjects]
    +SupportedObjects=0
    --- /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 @@
    +<?xml version="1.0"?>
    +<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
    +<PyObject module="node" class="Node" id="148584620">
    +<attr name="Profile" type="dict" id="148589396" >
    +</attr>
    +<attr name="Description" type="string" value="" />
    +<attr name="Dictionary" type="dict" id="148592132" >
    + <entry>
    + <key type="numeric" value="4096" />
    + <val type="numeric" value="302" />
    + </entry>
    + <entry>
    + <key type="numeric" value="4097" />
    + <val type="numeric" value="0" />
    + </entry>
    + <entry>
    + <key type="numeric" value="6144" />
    + <val type="list" id="148585004" >
    + <item type="string" value="{True:&quot;$NODEID+0x%X80&quot;%(base+1),False:0x80000000}[base&lt;4]" />
    + <item type="numeric" value="0" />
    + <item type="numeric" value="0" />
    + <item type="numeric" value="0" />
    + <item type="numeric" value="0" />
    + </val>
    + </entry>
    + <entry>
    + <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" />
    + </val>
    + </entry>
    + <entry>
    + <key type="numeric" value="4101" />
    + <val type="numeric" value="1073741952" />
    + </entry>
    + <entry>
    + <key type="numeric" value="4102" />
    + <val type="numeric" value="50000" />
    + </entry>
    + <entry>
    + <key type="numeric" value="8192" />
    + <val type="numeric" value="0" />
    + </entry>
    + <entry>
    + <key type="numeric" value="6656" />
    + <val type="list" id="148585228" >
    + <item type="numeric" value="268501000" />
    + </val>
    + </entry>
    + <entry>
    + <key type="numeric" value="5632" />
    + <val type="list" id="148585036" >
    + <item type="numeric" value="536870920" />
    + </val>
    + </entry>
    + <entry>
    + <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" />
    + </val>
    + </entry>
    + <entry>
    + <key type="numeric" value="4118" />
    + <val type="list" id="148585100" >
    + <item type="numeric" value="4195804" />
    + </val>
    + </entry>
    +</attr>
    +<attr name="SpecificMenu" type="list" id="148584044" >
    +</attr>
    +<attr name="ParamsDictionary" type="dict" id="148592268" >
    +</attr>
    +<attr name="UserMapping" type="dict" id="148592404" >
    + <entry>
    + <key type="numeric" value="8192" />
    + <val type="dict" id="148592540" >
    + <entry>
    + <key type="string" value="need" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="values" />
    + <val type="list" id="148585868" >
    + <item type="dict" id="148592676" >
    + <entry>
    + <key type="string" value="access" />
    + <val type="string" value="rw" />
    + </entry>
    + <entry>
    + <key type="string" value="pdo" />
    + <val type="True" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="type" />
    + <val type="numeric" value="5" />
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string">Read Inputs</val>
    + </entry>
    + </item>
    + </val>
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string">Read Inputs</val>
    + </entry>
    + <entry>
    + <key type="string" value="struct" />
    + <val type="numeric" value="1" />
    + </entry>
    + </val>
    + </entry>
    +</attr>
    +<attr name="DS302" type="dict" id="148592812" >
    + <entry>
    + <key type="numeric" value="7968" />
    + <val type="dict" id="148592948" >
    + <entry>
    + <key type="string" value="need" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="values" />
    + <val type="list" id="148584684" >
    + <item type="dict" id="148593084" >
    + <entry>
    + <key type="string" value="access" />
    + <val type="string" value="ro" />
    + </entry>
    + <entry>
    + <key type="string" value="pdo" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="type" />
    + <val type="numeric" value="5" />
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Number of Entries" />
    + </entry>
    + </item>
    + <item type="dict" id="148593220" >
    + <entry>
    + <key type="string" value="access" />
    + <val type="string" value="rw" />
    + </entry>
    + <entry>
    + <key type="string" value="pdo" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="type" />
    + <val type="numeric" value="15" />
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Store DCF for node %d[(sub)]" />
    + </entry>
    + <entry>
    + <key type="string" value="nbmax" />
    + <val type="numeric" value="127" />
    + </entry>
    + </item>
    + </val>
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Store DCF" />
    + </entry>
    + <entry>
    + <key type="string" value="struct" />
    + <val type="numeric" value="7" />
    + </entry>
    + </val>
    + </entry>
    + <entry>
    + <key type="numeric" value="7969" />
    + <val type="dict" id="148593356" >
    + <entry>
    + <key type="string" value="need" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="values" />
    + <val type="list" id="148585516" >
    + <item type="dict" id="148593492" >
    + <entry>
    + <key type="string" value="access" />
    + <val type="string" value="ro" />
    + </entry>
    + <entry>
    + <key type="string" value="pdo" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="type" />
    + <val type="numeric" value="5" />
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Number of Entries" />
    + </entry>
    + </item>
    + <item type="dict" id="148593628" >
    + <entry>
    + <key type="string" value="access" />
    + <val type="string" value="rw" />
    + </entry>
    + <entry>
    + <key type="string" value="pdo" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="type" />
    + <val type="numeric" value="2" />
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Storage Format for Node %d[(sub)]" />
    + </entry>
    + <entry>
    + <key type="string" value="nbmax" />
    + <val type="numeric" value="127" />
    + </entry>
    + </item>
    + </val>
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Storage Format" />
    + </entry>
    + <entry>
    + <key type="string" value="struct" />
    + <val type="numeric" value="7" />
    + </entry>
    + </val>
    + </entry>
    + <entry>
    + <key type="numeric" value="7970" />
    + <val type="dict" id="148593764" >
    + <entry>
    + <key type="string" value="need" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="values" />
    + <val type="list" id="148594956" >
    + <item type="dict" id="148593900" >
    + <entry>
    + <key type="string" value="access" />
    + <val type="string" value="ro" />
    + </entry>
    + <entry>
    + <key type="string" value="pdo" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="type" />
    + <val type="numeric" value="5" />
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Number of Entries" />
    + </entry>
    + </item>
    + <item type="dict" id="148594036" >
    + <entry>
    + <key type="string" value="access" />
    + <val type="string" value="rw" />
    + </entry>
    + <entry>
    + <key type="string" value="pdo" />
    + <val type="False" value="" />
    + </entry>
    + <entry>
    + <key type="string" value="type" />
    + <val type="numeric" value="15" />
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Concise DCF for Node %d[(sub)]" />
    + </entry>
    + <entry>
    + <key type="string" value="nbmax" />
    + <val type="numeric" value="127" />
    + </entry>
    + </item>
    + </val>
    + </entry>
    + <entry>
    + <key type="string" value="name" />
    + <val type="string" value="Concise DCF" />
    + </entry>
    + <entry>
    + <key type="string" value="struct" />
    + <val type="numeric" value="7" />
    + </entry>
    + </val>
    + </entry>
    +</attr>
    +<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>
    +</PyObject>
    --- /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 @@
    +[TOPOLOGY]
    +NetName=None
    +Nodes=0x01
    +Node64Present=0x01
    +Node64Name=micromod
    +Node64DCFName=PEAK MicroMod.eds
    +EDSBaseName=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 @@
    +1000 (Device Type): 12E
    +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 (Identity):
    +1018 01 (Vendor ID): 0
    +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 (Concise DCF):
    +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):
    +2000 (Read Inputs): 0
    +2240 (beremiz__IB0_1_64):
    +2240 01 (24576_1): 0
    +2240 02 (24578_1): 0
    +2340 (beremiz__IW0_1_64):
    +2340 01 (25601_2): 0
    +2340 02 (25601_3): 0
    +2440 (beremiz__ID0_1_64):
    +2440 01 (25638_2): 0
    +2440 02 (25638_3): 0
    +2440 03 (25638_4): 0
    +2440 04 (25638_1): 0
    +4340 (beremiz__QW0_1_64):
    +4340 01 (25617_1): 0
    +
    +********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 @@
    -*.pyc
    --- 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
    -
    -catalog = [
    - ('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 @@
    -*.pyc
    --- 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 @@
    -import keyword
    -
    -import wx
    -import wx.grid
    -import wx.stc as stc
    -import wx.lib.buttons
    -
    -from controls import CustomGrid, CustomTable, EditorPanel
    -
    -if wx.Platform == '__WXMSW__':
    - faces = { 'times': 'Times New Roman',
    - 'mono' : 'Courier New',
    - 'helv' : 'Arial',
    - 'other': 'Comic Sans MS',
    - 'size' : 10,
    - 'size2': 8,
    - }
    -else:
    - faces = { 'times': 'Times',
    - 'mono' : 'Courier',
    - 'helv' : 'Helvetica',
    - 'other': 'new century schoolbook',
    - 'size' : 12,
    - 'size2': 10,
    - }
    -
    -
    -def AppendMenu(parent, help, id, kind, text):
    - if wx.VERSION >= (2, 6, 0):
    - parent.Append(help=help, id=id, kind=kind, text=text)
    - else:
    - parent.Append(helpString=help, id=id, kind=kind, item=text)
    -
    -
    -[ID_CPPEDITOR,
    -] = [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):
    - old_length = len(old)
    - new_length = len(new)
    - common_length = min(old_length, new_length)
    - i = 0
    - for i in xrange(common_length):
    - if old[i] != new[i]:
    - break
    - if old_length < new_length:
    - if common_length > 0 and old[i] != new[i]:
    - return i + new_length - old_length
    - else:
    - 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]:
    - return i
    - else:
    - return i + 1
    - else:
    - return None
    -
    -class CppEditor(stc.StyledTextCtrl):
    -
    - fold_symbols = 3
    -
    - def __init__(self, parent, name, window, controler):
    - stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition,
    - wx.Size(0, 0), 0)
    -
    - 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.SetMargins(0,0)
    -
    - self.SetViewWhiteSpace(False)
    - #self.SetBufferedDraw(False)
    - #self.SetViewEOL(True)
    - #self.SetEOLMode(stc.STC_EOL_CRLF)
    - #self.SetUseAntiAliasing(True)
    -
    - self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
    - self.SetEdgeColumn(78)
    -
    - # 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())
    - self.RegisterImage(1,
    - wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
    - self.RegisterImage(2,
    - wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
    - self.RegisterImage(3,
    - wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
    -
    - # Indentation size
    - self.SetTabWidth(2)
    - self.SetUseTabs(0)
    -
    - self.Controler = controler
    - self.ParentWindow = window
    -
    - self.DisableEvents = True
    - self.Name = name
    - 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:
    - self.StartBuffering()
    - elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
    - self.Controler.EndBuffering()
    - self.StartBuffering()
    - self.CurrentAction = ("Add", event.GetPosition())
    - wx.CallAfter(self.RefreshModel)
    - elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
    - if self.CurrentAction == None:
    - self.StartBuffering()
    - elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
    - self.Controler.EndBuffering()
    - self.StartBuffering()
    - self.CurrentAction = ("Delete", event.GetPosition())
    - wx.CallAfter(self.RefreshModel)
    - event.Skip()
    -
    - def OnDoDrop(self, event):
    - self.ResetBuffer()
    - wx.CallAfter(self.RefreshModel)
    - event.Skip()
    -
    - # 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()
    -
    - def ResetBuffer(self):
    - if self.CurrentAction != None:
    - self.Controler.EndBuffering()
    - self.CurrentAction = None
    -
    - def RefreshView(self):
    - self.ResetBuffer()
    - self.DisableEvents = True
    - old_cursor_pos = self.GetCurrentPos()
    - old_text = self.GetText()
    - new_text = self.Controler.GetPartText(self.Name)
    - self.SetText(new_text)
    - new_cursor_pos = GetCursorPos(old_text, new_text)
    - if new_cursor_pos != None:
    - self.GotoPos(new_cursor_pos)
    - else:
    - self.GotoPos(old_cursor_pos)
    - self.ScrollToColumn(0)
    - self.EmptyUndoBuffer()
    - self.DisableEvents = False
    -
    - self.Colourise(0, -1)
    -
    - def DoGetBestSize(self):
    - return self.ParentWindow.GetPanelBestSize()
    -
    - def RefreshModel(self):
    - self.Controler.SetPartText(self.Name, self.GetText())
    -
    - def OnKeyPressed(self, event):
    - if self.CallTipActive():
    - self.CallTipCancel()
    - key = event.GetKeyCode()
    -
    - if key == 32 and event.ControlDown():
    - pos = self.GetCurrentPos()
    -
    - # Tips
    - if event.ShiftDown():
    - pass
    -## 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)')
    - # Code completion
    - else:
    - 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]))
    - else:
    - event.Skip()
    -
    - def OnKillFocus(self, event):
    - self.AutoCompCancel()
    - event.Skip()
    -
    - def OnUpdateUI(self, evt):
    - # check for matching braces
    - braceAtCaret = -1
    - braceOpposite = -1
    - charBefore = None
    - caretPos = self.GetCurrentPos()
    -
    - if caretPos > 0:
    - charBefore = self.GetCharAt(caretPos - 1)
    - styleBefore = self.GetStyleAt(caretPos - 1)
    -
    - # check before
    - if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
    - braceAtCaret = caretPos - 1
    -
    - # check after
    - if braceAtCaret < 0:
    - charAfter = self.GetCharAt(caretPos)
    - styleAfter = self.GetStyleAt(caretPos)
    -
    - if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
    - braceAtCaret = caretPos
    -
    - if braceAtCaret >= 0:
    - braceOpposite = self.BraceMatch(braceAtCaret)
    -
    - if braceAtCaret != -1 and braceOpposite == -1:
    - self.BraceBadLight(braceAtCaret)
    - else:
    - self.BraceHighlight(braceAtCaret, braceOpposite)
    - #pt = self.PointFromPosition(braceOpposite)
    - #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
    - #print pt
    - #self.Refresh(False)
    -
    -
    - def OnMarginClick(self, evt):
    - # fold and unfold as needed
    - if evt.GetMargin() == 2:
    - if evt.GetShift() and evt.GetControl():
    - self.FoldAll()
    - else:
    - lineClicked = self.LineFromPosition(evt.GetPosition())
    -
    - if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
    - if evt.GetShift():
    - self.SetFoldExpanded(lineClicked, True)
    - self.Expand(lineClicked, True, True, 1)
    - elif evt.GetControl():
    - if self.GetFoldExpanded(lineClicked):
    - self.SetFoldExpanded(lineClicked, False)
    - self.Expand(lineClicked, False, True, 0)
    - else:
    - self.SetFoldExpanded(lineClicked, True)
    - self.Expand(lineClicked, True, True, 100)
    - else:
    - self.ToggleFold(lineClicked)
    -
    -
    - def FoldAll(self):
    - lineCount = self.GetLineCount()
    - expanding = True
    -
    - # 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)
    - break
    -
    - lineNum = 0
    -
    - while lineNum < lineCount:
    - level = self.GetFoldLevel(lineNum)
    - if level & stc.STC_FOLDLEVELHEADERFLAG and \
    - (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
    -
    - if expanding:
    - self.SetFoldExpanded(lineNum, True)
    - lineNum = self.Expand(lineNum, True)
    - lineNum = lineNum - 1
    - else:
    - lastChild = self.GetLastChild(lineNum, -1)
    - self.SetFoldExpanded(lineNum, False)
    -
    - if lastChild > lineNum:
    - self.HideLines(lineNum+1, lastChild)
    -
    - lineNum = lineNum + 1
    -
    -
    -
    - def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
    - lastChild = self.GetLastChild(line, level)
    - line = line + 1
    -
    - while line <= lastChild:
    - if force:
    - if visLevels > 0:
    - self.ShowLines(line, line)
    - else:
    - self.HideLines(line, line)
    - else:
    - if doExpand:
    - self.ShowLines(line, line)
    -
    - if level == -1:
    - level = self.GetFoldLevel(line)
    -
    - if level & stc.STC_FOLDLEVELHEADERFLAG:
    - if force:
    - if visLevels > 1:
    - self.SetFoldExpanded(line, True)
    - else:
    - self.SetFoldExpanded(line, False)
    -
    - line = self.Expand(line, doExpand, force, visLevels-1)
    -
    - else:
    - if doExpand and self.GetFoldExpanded(line):
    - line = self.Expand(line, True, force, visLevels-1)
    - else:
    - line = self.Expand(line, False, force, visLevels-1)
    - else:
    - line = line + 1
    -
    - return line
    -
    - def Cut(self):
    - self.ResetBuffer()
    - self.DisableEvents = True
    - self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
    - self.DisableEvents = False
    - self.RefreshModel()
    - self.RefreshBuffer()
    -
    - def Copy(self):
    - self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
    -
    - def Paste(self):
    - self.ResetBuffer()
    - self.DisableEvents = True
    - self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
    - self.DisableEvents = False
    - self.RefreshModel()
    - self.RefreshBuffer()
    -
    -
    -#-------------------------------------------------------------------------------
    -# Helper for VariablesGrid values
    -#-------------------------------------------------------------------------------
    -
    -class VariablesTable(CustomTable):
    -
    - def GetValue(self, row, col):
    - if row < self.GetNumberRows():
    - if col == 0:
    - return row + 1
    - else:
    - 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.
    - """
    -
    - typelist = None
    - accesslist = None
    - for row in range(self.GetNumberRows()):
    - for col in range(self.GetNumberCols()):
    - editor = None
    - renderer = None
    - colname = self.GetColLabelValue(col, False)
    -
    - if colname == "Name":
    - editor = wx.grid.GridCellTextEditor()
    - elif colname == "Class":
    - editor = wx.grid.GridCellChoiceEditor()
    - editor.SetParameters("input,memory,output")
    - elif colname == "Type":
    - pass
    - else:
    - 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):
    - if id is not None:
    - event(self, id, function)
    - else:
    - event(self, 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)
    - else:
    - 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)
    -
    - self._init_sizers()
    -
    - 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())
    - self.RefreshModel()
    - self.RefreshView()
    - return new_row
    - setattr(self.VariablesGrid, "_AddRow", _AddVariable)
    -
    - def _DeleteVariable(row):
    - self.Table.RemoveRow(row)
    - self.RefreshModel()
    - self.RefreshView()
    - setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
    -
    - def _MoveVariable(row, move):
    - new_row = self.Table.MoveRow(row, move)
    - if new_row != row:
    - self.RefreshModel()
    - self.RefreshView()
    - return new_row
    - 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())
    - self.RefreshBuffer()
    -
    - # Buffer the last model state
    - def RefreshBuffer(self):
    - self.Controler.BufferCFile()
    - self.ParentWindow.RefreshTitle()
    - self.ParentWindow.RefreshFileMenu()
    - self.ParentWindow.RefreshEditMenu()
    - self.ParentWindow.RefreshPageTitles()
    -
    - def RefreshView(self):
    - 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):
    - self.RefreshModel()
    - wx.CallAfter(self.RefreshView)
    - event.Skip()
    -
    - 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():
    - new_id = wx.NewId()
    - 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):
    - new_id = wx.NewId()
    - 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())
    - type_menu.Destroy()
    - event.Veto()
    - else:
    - event.Skip()
    -
    - def GetVariableTypeFunction(self, base_type):
    - def VariableTypeFunction(event):
    - row = self.VariablesGrid.GetGridCursorRow()
    - self.Table.SetValueByName(row, "Type", base_type)
    - self.Table.ResetView(self.VariablesGrid)
    - self.RefreshModel()
    - self.RefreshView()
    - event.Skip()
    - return VariableTypeFunction
    -
    - def OnVariablesGridCellLeftClick(self, event):
    - if event.GetCol() == 0:
    - row = event.GetRow()
    - num = 0
    - if self.Table.GetValueByName(row, "Class") == "input":
    - dir = "%I"
    - for i in xrange(row):
    - if self.Table.GetValueByName(i, "Class") == "input":
    - num += 1
    - elif self.Table.GetValueByName(row, "Class") == "memory":
    - dir = "%M"
    - for i in xrange(row):
    - if self.Table.GetValueByName(i, "Class") == "memory":
    - num += 1
    - else:
    - dir = "%Q"
    - for i in xrange(row):
    - if self.Table.GetValueByName(i, "Class") == "output":
    - num += 1
    - 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()
    - event.Skip()
    -
    -
    -#-------------------------------------------------------------------------------
    -# SVGUIEditor Main Frame Class
    -#-------------------------------------------------------------------------------
    -
    -CFILE_PARTS = [
    - ("Includes", CppEditor),
    - ("Variables", VariablesEditor),
    - ("Globals", CppEditor),
    - ("Init", CppEditor),
    - ("CleanUp", CppEditor),
    - ("Retrieve", CppEditor),
    - ("Publish", CppEditor),
    -]
    -
    -#----------------------------------------------------------------------
    -# different icons for the collapsed/expanded states.
    -# Taken from standard Windows XP collapsed/expanded states.
    -#----------------------------------------------------------------------
    -
    -def GetCollapsedIconData():
    - return \
    -'\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():
    - import cStringIO
    - stream = cStringIO.StringIO(GetCollapsedIconData())
    - return wx.ImageFromStream(stream)
    -
    -#----------------------------------------------------------------------
    -def GetExpandedIconData():
    - return \
    -'\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\
    -`\x82'
    -
    -def GetExpandedIconBitmap():
    - return wx.BitmapFromImage(GetExpandedIconImage())
    -
    -def GetExpandedIconImage():
    - import cStringIO
    - 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 myDef and parDef:
    - if wx.Platform == "__WXMAC__":
    - brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
    - elif wx.Platform == "__WXMSW__":
    - if self.DoEraseBackground(dc):
    - brush = None
    - elif myDef and not parDef:
    - colBg = self.GetParent().GetBackgroundColour()
    - brush = wx.Brush(colBg, wx.SOLID)
    - return brush
    -
    - def DrawLabel(self, dc, width, height, dx=0, dy=0):
    - bmp = self.bmpLabel
    - if bmp is not None: # if the bitmap is used
    - if self.bmpDisabled and not self.IsEnabled():
    - bmp = self.bmpDisabled
    - if self.bmpFocus and self.hasFocus:
    - bmp = self.bmpFocus
    - if self.bmpSelected and not self.up:
    - bmp = self.bmpSelected
    - bw,bh = bmp.GetWidth(), bmp.GetHeight()
    - hasMask = bmp.GetMask() is not None
    - else:
    - bw = bh = 0 # no bitmap -> size is zero
    -
    - dc.SetFont(self.GetFont())
    - if self.IsEnabled():
    - dc.SetTextForeground(self.GetForegroundColour())
    - else:
    - dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
    -
    - label = self.GetLabel()
    - tw, th = dc.GetTextExtent(label) # size of text
    -
    - if bmp is not None:
    - 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.Panels = {}
    - 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_id = wx.NewId()
    - 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)
    - else:
    - panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
    - self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
    - panel.Hide()
    -
    - 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)))
    -
    - def __del__(self):
    - self.Controler.OnCloseEditor(self)
    -
    - def GetTitle(self):
    - fullname = self.Controler.CTNFullName()
    - if not self.Controler.CFileIsSaved():
    - return "~%s~" % fullname
    - return fullname
    -
    - def GetBufferState(self):
    - return self.Controler.GetBufferState()
    -
    - def Undo(self):
    - self.Controler.LoadPrevious()
    - self.RefreshView()
    -
    - def Redo(self):
    - self.Controler.LoadNext()
    - self.RefreshView()
    -
    - def HasNoModel(self):
    - return False
    -
    - def RefreshView(self):
    - for infos in self.Panels.itervalues():
    - infos["panel"].RefreshView()
    -
    - def GenPanelButtonCallback(self, name):
    - def PanelButtonCallback(event):
    - self.TogglePanel(name)
    - 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)
    - infos["panel"].Show()
    - 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)
    - infos["panel"].Hide()
    - self.MainSizer.RemoveGrowableRow(infos["row"])
    -
    - self.RefreshSizerLayout()
    -
    - def TogglePanel(self, name):
    - infos = self.Panels.get(name, None)
    - if infos is not None:
    - infos["expanded"] = not infos["expanded"]
    - infos["button"].SetToggle(infos["expanded"])
    - if infos["expanded"]:
    - infos["panel"].Show()
    - self.MainSizer.AddGrowableRow(infos["row"])
    - else:
    - infos["panel"].Hide()
    - self.MainSizer.RemoveGrowableRow(infos["row"])
    -
    - self.RefreshSizerLayout()
    -
    - def RefreshSizerLayout(self):
    - expand_spacer = True
    - for infos in self.Panels.itervalues():
    - expand_spacer = expand_spacer and not infos["expanded"]
    -
    - if self.SpacerExpanded != expand_spacer:
    - self.SpacerExpanded = expand_spacer
    - if expand_spacer:
    - self.Spacer.Show()
    - self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
    - else:
    - self.Spacer.Hide()
    - 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 @@
    -C extension
    \ 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 @@
    -from c_ext import *
    --- 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 @@
    -import wx
    -import os
    -from xml.dom import minidom
    -import cPickle
    -
    -from xmlclass import *
    -
    -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"}
    -
    -class _Cfile:
    - XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    - <xsd:element name="CExtension">
    - <xsd:complexType>
    - <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
    - <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/>
    - </xsd:complexType>
    - </xsd:element>
    - </xsd:schema>
    - """
    - EditorType = CFileEditor
    -
    - def __init__(self):
    - filepath = self.CFileName()
    -
    - self.CFile = CFileClasses["CFile"]()
    - if os.path.isfile(filepath):
    - xmlfile = open(filepath, 'r')
    - tree = minidom.parse(xmlfile)
    - xmlfile.close()
    -
    - for child in tree.childNodes:
    - if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
    - self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
    - self.CreateCFileBuffer(True)
    - else:
    - self.CreateCFileBuffer(False)
    - self.OnCTNSave()
    -
    - def CFileName(self):
    - 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([])
    - for var in variables:
    - variable = CFileClasses["variables_variable"]()
    - variable.setname(var["Name"])
    - variable.settype(var["Type"])
    - variable.setclass(var["Class"])
    - self.CFile.variables.appendvariable(variable)
    -
    - def GetVariables(self):
    - datas = []
    - for var in self.CFile.variables.getvariable():
    - datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
    - return datas
    -
    - def GetVariableLocationTree(self):
    - '''See ConfigTreeNode.GetVariableLocationTree() for a description.'''
    -
    - current_location = ".".join(map(str, self.GetCurrentLocation()))
    -
    - vars = []
    - input = memory = output = 0
    - for var in self.CFile.variables.getvariable():
    - var_size = self.GetSizeOfType(var.gettype())
    - var_location = ""
    - 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)
    - input += 1
    - 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)
    - memory += 1
    - else:
    - var_class = LOCATION_VAR_OUTPUT
    - if var_size is not None:
    - var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
    - output += 1
    - vars.append({"name": var.getname(),
    - "type": var_class,
    - "size": var_size,
    - "IEC_type": var.gettype(),
    - "var_name": var.getname(),
    - "location": var_location,
    - "description": "",
    - "children": []})
    -
    - return {"name": self.BaseParams.getName(),
    - "type": LOCATION_CONFNODE,
    - "location": self.GetFullIEC_Channel(),
    - "children": vars}
    -
    - def SetPartText(self, name, text):
    - if name == "Includes":
    - self.CFile.includes.settext(text)
    - elif name == "Globals":
    - self.CFile.globals.settext(text)
    - elif name == "Init":
    - 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):
    - if name == "Includes":
    - return self.CFile.includes.gettext()
    - elif name == "Globals":
    - return self.CFile.globals.gettext()
    - elif name == "Init":
    - 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()
    - return ""
    -
    - ConfNodeMethods = [
    - {"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()
    -
    - def OnCTNSave(self):
    - 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"))
    - xmlfile.close()
    -
    - self.MarkCFileAsSaved()
    - return True
    -
    - def CTNGenerate_C(self, buildpath, locations):
    - """
    - Generate C code
    - @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    - @param locations: List of complete variables locations \
    - [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    - "NAME" : name of the variable (generally "__IW0_1_2" style)
    - "DIR" : direction "Q","I" or "M"
    - "SIZE" : size "X", "B", "W", "D", "L"
    - "LOC" : tuple of interger for IEC location (0,1,2,...)
    - }, ...]
    - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    - """
    - current_location = self.GetCurrentLocation()
    - # define a unique name for the generated C file
    - location_str = "_".join(map(str, current_location))
    -
    - text = "/* Code generated by Beremiz c_ext confnode */\n\n"
    -
    - # Adding includes
    - text += "/* User includes */\n"
    - text += self.CFile.includes.gettext()
    - text += "\n"
    -
    - text += """/* Beremiz c_ext confnode includes */
    -#ifdef _WINDOWS_H
    - #include "iec_types.h"
    -#else
    - #include "iec_std_lib.h"
    -#endif
    -
    -"""
    -
    - # Adding variables
    - vars = []
    - 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)
    - inputs += 1
    - elif variable.getclass() == "memory":
    - var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
    - memories += 1
    - else:
    - var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
    - outputs += 1
    - vars.append(var)
    - text += "/* Beremiz c_ext confnode user variables definition */\n"
    - base_types = self.GetCTRoot().GetBaseTypes()
    - for var in vars:
    - if var["Type"] in base_types:
    - prefix = "IEC_"
    - else:
    - prefix = ""
    - 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"
    - for var in vars:
    - text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
    - text += "\n"
    -
    - # 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 += " return 0;\n"
    - text += "\n}\n\n"
    -
    - text += "void __cleanup_%s(void)\n{\n"%location_str
    - text += self.CFile.cleanUpFunction.gettext()
    - text += "\n}\n\n"
    -
    - text += "void __retrieve_%s(void)\n{\n"%location_str
    - text += self.CFile.retrieveFunction.gettext()
    - text += "\n}\n\n"
    -
    - text += "void __publish_%s(void)\n{\n"%location_str
    - text += self.CFile.publishFunction.gettext()
    - text += "\n}\n\n"
    -
    - Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
    - cfile = open(Gen_Cfile_path,'w')
    - cfile.write(text)
    - cfile.close()
    -
    - 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
    - """
    - def Copy(self, model):
    - return cPickle.loads(cPickle.dumps(model))
    -
    - def CreateCFileBuffer(self, saved):
    - self.Buffering = False
    - self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
    -
    - def BufferCFile(self):
    - self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
    -
    - def StartBuffering(self):
    - self.Buffering = True
    -
    - def EndBuffering(self):
    - if self.Buffering:
    - self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
    - self.Buffering = False
    -
    - def MarkCFileAsSaved(self):
    - self.EndBuffering()
    - self.CFileBuffer.CurrentSaved()
    -
    - def CFileIsSaved(self):
    - return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
    -
    - def LoadPrevious(self):
    - self.EndBuffering()
    - self.CFile = cPickle.loads(self.CFileBuffer.Previous())
    -
    - def LoadNext(self):
    - 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
    -
    -class RootClass:
    -
    - CTNChildrenTypes = [("C_File",_Cfile, "C file")]
    -
    - def CTNGenerate_C(self, buildpath, locations):
    - return [],"",False
    -
    -
    --- 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:complexType>
    - <xsd:sequence>
    - <xsd:element name="includes" type="cext:CCode"/>
    - <xsd:element name="variables">
    - <xsd:complexType>
    - <xsd:sequence>
    - <xsd:element name="variable" minOccurs="0" maxOccurs="unbounded">
    - <xsd:complexType>
    - <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:simpleType>
    - <xsd:restriction base="xsd:string">
    - <xsd:enumeration value="input"/>
    - <xsd:enumeration value="memory"/>
    - <xsd:enumeration value="output"/>
    - </xsd:restriction>
    - </xsd:simpleType>
    - </xsd:attribute>
    - </xsd:complexType>
    - </xsd:element>
    - </xsd:sequence>
    - </xsd:complexType>
    - </xsd:element>
    - <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:sequence>
    - </xsd:complexType>
    - </xsd:element>
    - <xsd:complexType name="CCode">
    - <xsd:annotation>
    - <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
    - </xsd:annotation>
    - <xsd:sequence>
    - <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
    - </xsd:sequence>
    - </xsd:complexType>
    -</xsd:schema>
    --- 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 @@
    -*.pyc
    --- 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 @@
    -import os, sys
    -base_folder = os.path.split(sys.path[0])[0]
    -CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
    -
    -import wx
    -
    -from subindextable import EditingPanel
    -from networkedit import NetworkEditorTemplate
    -from controls import EditorPanel
    -
    -[ID_NETWORKEDITOR,
    -] = [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):
    -
    - ID = ID_NETWORKEDITOR
    -
    - 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)
    -
    - self._init_sizers()
    -
    - 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()
    -
    - def __del__(self):
    - 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))))
    - else:
    - 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):
    - pass
    -
    - def RefreshConfNodeMenu(self, confnode_menu):
    - confnode_menu.Enable(ID_NETWORKEDITORCONFNODEMENUMASTER, self.NetworkNodes.GetSelection() == 0)
    -
    - def GetTitle(self):
    - fullname = self.Controler.CTNFullName()
    - if not self.Manager.CurrentIsSaved():
    - return "~%s~" % fullname
    - return fullname
    -
    - def RefreshView(self):
    - 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 @@
    -CANOpen
    \ 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 @@
    -import os, sys
    -base_folder = os.path.split(sys.path[0])[0]
    -CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
    -
    -import wx
    -
    -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)))
    -
    - def __del__(self):
    - self.Controler.OnCloseEditor(self)
    -
    - def GetConfNodeMenuItems(self):
    - if self.Editable:
    - 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))))
    - else:
    - 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))]
    - return []
    -
    - def RefreshConfNodeMenu(self, confnode_menu):
    - confnode_menu.Enable(ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, False)
    -
    - def GetTitle(self):
    - fullname = self.Controler.CTNFullName()
    - if not self.Controler.CurrentIsSaved():
    - return "~%s~" % fullname
    - return fullname
    -
    - def RefreshView(self):
    - self.Editor.RefreshIndexList()
    -
    - def RefreshCurrentIndexList(self):
    - self.RefreshView()
    -
    - 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 @@
    -import os, sys
    -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
    -import wx
    -
    -from SlaveEditor import SlaveEditor
    -from NetworkEditor import NetworkEditor
    -
    -from gnosis.xml.pickle import *
    -from gnosis.xml.pickle.util import setParanoia
    -setParanoia(0)
    -
    -if wx.Platform == '__WXMSW__':
    - DEFAULT_SETTINGS = {
    - "CAN_Driver": "can_tcp_win32",
    - "CAN_Device": "127.0.0.1",
    - "CAN_Baudrate": "125K",
    - "Slave_NodeId": 2,
    - "Master_NodeId": 1,
    - }
    -else:
    - DEFAULT_SETTINGS = {
    - "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so",
    - "CAN_Device": "vcan0",
    - "CAN_Baudrate": "125K",
    - "Slave_NodeId": 2,
    - "Master_NodeId": 1,
    - }
    -
    -#--------------------------------------------------
    -# SLAVE
    -#--------------------------------------------------
    -
    -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:complexType>
    - <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:simpleType>
    - <xsd:restriction base="xsd:integer">
    - <xsd:minInclusive value="1"/>
    - <xsd:maxInclusive value="99"/>
    - </xsd:restriction>
    - </xsd:simpleType>
    - </xsd:attribute>
    - </xsd:complexType>
    - </xsd:element>
    - </xsd:schema>
    - """ % DEFAULT_SETTINGS
    -
    - EditorType = SlaveEditor
    -
    - def __init__(self):
    - # TODO change netname when name change
    - NodeManager.__init__(self)
    - odfilepath = self.GetSlaveODPath()
    - if(os.path.isfile(odfilepath)):
    - self.OpenFileInCurrent(odfilepath)
    - else:
    - self.FilePath = ""
    - 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
    - "slave", # Type
    - description,# description
    - profile, # profile
    - filepath, # prfile filepath
    - NMT, # NMT
    - options) # options
    - else:
    - self.CreateNewNode("SlaveNode", # Name - will be changed at build time
    - 0x00, # NodeID - will be changed at build time
    - "slave", # Type
    - "", # description
    - "None", # profile
    - "", # prfile filepath
    - "heartbeat", # NMT
    - []) # options
    - dialog.Destroy()
    - self.OnCTNSave()
    -
    - def GetSlaveODPath(self):
    - return os.path.join(self.CTNPath(), 'slave.od')
    -
    - def GetCanDevice(self):
    - return self.CanFestivalSlaveNode.getCan_Device()
    -
    - def _OpenView(self):
    - ConfigTreeNode._OpenView(self)
    - if self._View is not None:
    - self._View.SetBusId(self.GetCurrentLocation())
    -
    - ConfNodeMethods = [
    - {"bitmap" : os.path.join("images", "NetworkEdit"),
    - "name" : "Edit slave",
    - "tooltip" : "Edit CanOpen slave with ObjdictEdit",
    - "method" : "_OpenView"},
    - ]
    -
    - def OnCTNClose(self):
    - if self._View:
    - self._View.Close()
    -
    - def CTNTestModified(self):
    - return self.ChangesToSave or self.OneFileHasChanged()
    -
    - def OnCTNSave(self):
    - 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())
    -
    - return result
    -
    - def CTNGenerate_C(self, buildpath, locations):
    - """
    - Generate C code
    - @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    - @param locations: List of complete variables locations \
    - [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    - "NAME" : name of the variable (generally "__IW0_1_2" style)
    - "DIR" : direction "Q","I" or "M"
    - "SIZE" : size "X", "B", "W", "D", "L"
    - "LOC" : tuple of interger for IEC location (0,1,2,...)
    - }, ...]
    - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    - """
    - current_location = self.GetCurrentLocation()
    - # define a unique name for the generated C file
    - 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)
    - if res :
    - raise Exception, res
    - res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
    - if res :
    - raise Exception, res
    - return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
    -
    - def LoadPrevious(self):
    - self.LoadCurrentPrevious()
    -
    - def LoadNext(self):
    - self.LoadCurrentNext()
    -
    - def GetBufferState(self):
    - return self.GetCurrentBufferState()
    -
    -#--------------------------------------------------
    -# MASTER
    -#--------------------------------------------------
    -
    -class MiniNodeManager(NodeManager):
    -
    - def __init__(self, parent, filepath, fullname):
    - NodeManager.__init__(self)
    -
    - self.OpenFileInCurrent(filepath)
    -
    - self.Parent = parent
    - self.Fullname = fullname
    -
    - def OnCloseEditor(self, view):
    - self.Parent.OnCloseEditor(view)
    -
    - def CTNFullName(self):
    - return self.Fullname
    -
    - 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:complexType>
    - <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"/>
    - </xsd:complexType>
    - </xsd:element>
    - </xsd:schema>
    - """ % DEFAULT_SETTINGS
    -
    - EditorType = NetworkEditor
    -
    - def __init__(self):
    - 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)
    -
    - return result
    -
    - def _OpenView(self):
    - ConfigTreeNode._OpenView(self)
    - if self._View is not None:
    - self._View.SetBusId(self.GetCurrentLocation())
    -
    - _GeneratedView = None
    - 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"))
    - return
    -
    - masterpath = os.path.join(buildpath, "MasterGenerated.od")
    - if not os.path.exists(masterpath):
    - self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
    - return
    -
    - 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)
    -
    - ConfNodeMethods = [
    - {"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
    -
    - def OnCTNClose(self):
    - ConfigTreeNode.OnCTNClose(self)
    - self._CloseGenerateView()
    - return True
    -
    - def CTNTestModified(self):
    - return self.ChangesToSave or self.HasChanged()
    -
    - def OnCTNSave(self):
    - self.SetRoot(self.CTNPath())
    - return self.SaveProject() is None
    -
    - def CTNGenerate_C(self, buildpath, locations):
    - """
    - Generate C code
    - @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    - @param locations: List of complete variables locations \
    - [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    - "NAME" : name of the variable (generally "__IW0_1_2" style)
    - "DIR" : direction "Q","I" or "M"
    - "SIZE" : size "X", "B", "W", "D", "L"
    - "LOC" : tuple of interger for IEC location (0,1,2,...)
    - }, ...]
    - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    - """
    - 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
    - try:
    - 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
    - # Do generate C file.
    - res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
    - if res :
    - raise Exception, res
    -
    - file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
    - dump(master, file)
    - file.close()
    -
    - return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
    -
    - def LoadPrevious(self):
    - self.Manager.LoadCurrentPrevious()
    -
    - def LoadNext(self):
    - self.Manager.LoadCurrentNext()
    -
    - def GetBufferState(self):
    - return self.Manager.GetCurrentBufferState()
    -
    -class RootClass:
    - XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    - <xsd:element name="CanFestivalInstance">
    - <xsd:complexType>
    - <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"/>
    - </xsd:complexType>
    - </xsd:element>
    - </xsd:schema>
    - """ % DEFAULT_SETTINGS
    -
    - CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"),
    - ("CanOpenSlave",_SlaveCTN, "CanOpen Slave")]
    - def GetParamsAttributes(self, path = None):
    - infos = ConfigTreeNode.GetParamsAttributes(self, path = None)
    - for element in infos:
    - 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
    - return infos
    -
    - 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'
    - else:
    - can_driver += '.dll'
    - return can_driver
    -
    - def CTNGenerate_C(self, buildpath, locations):
    -
    - format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
    - "candriver" : self.GetCanDriver(),
    - "nodes_includes" : "",
    - "board_decls" : "",
    - "nodes_init" : "",
    - "nodes_open" : "",
    - "nodes_stop" : "",
    - "nodes_close" : "",
    - "nodes_send_sync" : "",
    - "nodes_proceed_sync" : "",
    - "slavebootups" : "",
    - "slavebootup_register" : "",
    - "post_sync" : "",
    - "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)
    - if child_data is None:
    - # Not a slave -> master
    - child_data = getattr(child, "CanFestivalNode")
    - # Apply sync setting
    - format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n '%(
    - nodename,
    - 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()
    - if len(SlaveIDs) == 0:
    - # define post_SlaveBootup lookup functions
    - format_dict["slavebootups"] += (
    - "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
    - else:
    - for id in SlaveIDs:
    - 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)+
    - " switch(nodeId){\n")
    - # one case per declared node, mark node as booted
    - for id in SlaveIDs:
    - format_dict["slavebootups"] += (
    - " case %d:\n"%(id)+
    - " %s_slave_%d_booted = 1;\n"%(nodename, id)+
    - " break;\n")
    - format_dict["slavebootups"] += (
    - " default:\n"+
    - " break;\n"+
    - " }\n"+
    - " if( ")
    - # 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"+
    - "}\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))
    - else:
    - # Slave node
    - align = child_data.getSync_Align()
    - align_ratio=child_data.getSync_Align_Ratio()
    - if align > 0:
    - 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(-1);\n"+
    - " }else{\n"+
    - " align_tick(%d);\n"%(align_ratio)+
    - " }\n"+
    - "}\n")
    - 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 '%(
    - nodename,
    - 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'%(
    - nodename,
    - child.GetCanDevice(),
    - 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')
    - f.write(cf_main)
    - f.close()
    -
    - 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*/
    -%(nodes_includes)s
    -
    -#define BOARD_DECL(nodename, busname, baudrate)\
    - s_BOARD nodename##Board = {busname, baudrate};
    -
    -/* CAN channels declaration */
    -%(board_decls)s
    -
    -/* 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 */
    -%(slavebootups)s
    -
    -/* One slave node post_sync callback.
    - * Used to align PLC tick-time on CANopen SYNC
    - */
    -%(post_sync)s
    -
    -#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);\
    - /* init */\
    - 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
    - %(post_sync_register)s
    - %(nodes_init)s
    -}
    -
    -#define NODE_STOP(nodename) \
    - if(init_level-- > 0)\
    - {\
    - masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\
    - setState(&nodename##_Data, Stopped);\
    - }
    -
    -void Exit(CO_Data* d, UNS32 id)
    -{
    - %(nodes_stop)s
    -}
    -
    -#define NODE_CLOSE(nodename) \
    - if(init_level_c-- > 0)\
    - {\
    - canClose(&nodename##_Data);\
    - }
    -
    -void __cleanup_%(locstr)s(void)
    -{
    - // Stop timer thread
    - if(init_level-- > 0){
    - int init_level_c = init_level;
    - StopTimerLoop(&Exit);
    - %(nodes_close)s
    - }
    -
    - TimerCleanup();
    -}
    -
    -#ifndef stderr
    -#define fprintf(...)
    -#define fflush(...)
    -#endif
    -
    -#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);\
    - fflush(stderr);\
    - return -1;\
    - }\
    - init_level++;
    -
    -/*************************** 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");\
    - fflush(stderr);\
    - return -1;\
    - }
    -#endif
    -
    - TimerInit();
    -
    - %(nodes_open)s
    -
    - // Start timer thread
    - StartTimerLoop(&InitNodes);
    - init_level++;
    - return 0;
    -}
    -
    -#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
    - * */
    - EnterMutex();
    - /* Send Sync */
    - %(nodes_send_sync)s
    -}
    -
    -#define NODE_PROCEED_SYNC(nodename)\
    - proceedSYNC(&nodename##_Data);
    -
    -void __publish_%(locstr)s(void)
    -{
    - /* Process sync event */
    - %(nodes_proceed_sync)s
    - LeaveMutex();
    -}
    -
    --- 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 @@
    -#!/usr/bin/env python
    -# -*- coding: utf-8 -*-
    -
    -#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
    -
    -from types import *
    -
    -# 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
    -RPDO = 1
    -TPDO = 2
    -
    -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):
    - pass
    -
    -
    -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)]
    - list_car.reverse()
    - 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 node: 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 = []
    - if type & RPDO:
    - indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
    - if type & TPDO:
    - indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF])
    - if not parameters:
    - return [idx + 0x200 for idx in indexes]
    - else:
    - return indexes
    -
    -
    -def SearchNodePDOMapping(loc_infos, node):
    - """
    - Find the PDO indexes of a node
    - @param node: 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)
    - if values != None:
    - for subindex, mapping in enumerate(values):
    - if subindex != 0 and mapping & 0xFFFFFF00 == model:
    - return PDOidx, subindex
    - return None
    -
    -
    -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)
    - # Re-Enable PDO
    - # ---- 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)
    - nbparams = 3
    - 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)
    - nbparams += 1
    - # Map Variables
    - 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)
    - nbparams += 1
    - return dcfdata, nbparams
    -
    -class ConciseDCFGenerator:
    -
    - def __init__(self, nodelist, nodename):
    - # Dictionary of location informations classed by name
    - self.IECLocations = {}
    - # 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
    - @param node: node
    - @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
    - if pdo_cobid > 0x600 :
    - 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"]
    - node.SetNodeID(nodeid)
    -
    - RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
    -
    - # Get Slave's default SDO server parameters
    - RSDO_cobid = node.GetEntry(0x1200,0x01)
    - if not RSDO_cobid:
    - RSDO_cobid = 0x600 + nodeid
    - TSDO_cobid = node.GetEntry(0x1200,0x02)
    - if not TSDO_cobid:
    - 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):
    - """
    - Return MasterNode.
    - """
    - return self.MasterNode
    -
    - 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]]
    - tmpnbparams.reverse()
    - nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
    - data = nodeDCF[4:] + data
    -
    - # Build new DCF
    - 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]
    - else:
    - index = start_index
    -
    - # 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 cobid == 0:
    - if len(self.ListCobIDAvailable) == 0:
    - return None
    - # 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]
    - index += 1
    - return None
    -
    - 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
    - if sync_TPDOs:
    - return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
    - else:
    - return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
    - return 0, ""
    -
    - 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
    - else:
    - # 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)
    - elif len(loc) == 2:
    - continue
    -
    - 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)
    -
    - # Get the entry info
    - subentry_infos = node.GetSubentryInfos(index, subindex)
    -
    - # If a PDO mappable
    - if subentry_infos and subentry_infos["pdo"]:
    - if sizelocation == "X" and len(loc) > 3:
    - numbit = 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)
    - else:
    - numbit = None
    -
    - 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}
    - else:
    - 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)
    - if result != None:
    - 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:
    - if sync_TPDOs:
    - # Change TransmitType to SYNCHRONE
    - data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, [])
    - else:
    - # 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)
    -
    - mapping = [None]
    - values = node.GetEntry(index)
    - # Store the size of each entry mapped in PDO
    - for value in values[1:]:
    - if value != 0:
    - 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)
    - else:
    - self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
    -
    - else:
    - # 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
    - nbparams = 0
    - dataparams = ""
    -
    - # Generate the best PDO mapping for each type of PDO
    - for pdotype in (TPDO, RPDO):
    - if len(locations[pdotype]) > 0:
    - pdosize = 0
    - pdomapping = []
    - result = self.GetEmptyPDO(nodeid, pdotype)
    - if result is None:
    - 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)
    - dataparams += data
    - nbparams += nbaddedparams
    - pdosize = loc_infos["size"]
    - pdomapping = [(name, loc_infos)]
    - result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
    - if result is None:
    - raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
    - pdoindex, pdocobid, pdonbparams = result
    - else:
    - 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)
    - dataparams += data
    - 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:
    - current_idx = idx
    -
    - # 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
    - if sync_TPDOs:
    - self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
    - else:
    - self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
    -
    - mapping = []
    - for item in pdo_infos["mapping"]:
    - if isinstance(item, ListType):
    - mapping.extend(item)
    - else:
    - mapping.append(item)
    -
    - # Add some subentries to PDO mapping if there is not enough
    - if len(mapping) > 1:
    - self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
    -
    - # Generate MasterNode's PDO mapping
    - for subindex, variable in enumerate(mapping):
    - if subindex == 0:
    - continue
    - new_index = False
    -
    - if isinstance(variable, (IntType, LongType)):
    - # If variable is an integer then variable is unexpected
    - self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
    - else:
    - 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"]
    -
    - # Generate entry name
    - 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:
    - # Entry doesn't exist
    - if not self.MasterNode.IsEntry(mapvariableidx):
    - # Add entry to MasterNode
    - self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
    - new_index = True
    - nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
    - else:
    - # 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
    - else:
    - break
    -
    - # 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
    - else:
    - subindexname = "%(index)d_%(subindex)d"%variable_infos
    - # If entry have just been created, no subentry have to be added
    - if not new_index:
    - self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode)
    - nbsubentries += 1
    - # 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)
    - if typeinfos != None:
    - 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):
    - IECLocations = {}
    - pointers = {}
    - 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
    - else:
    - # 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)
    - elif len(loc) != 2:
    - continue
    -
    - # 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)
    -
    - # Get the entry info
    - 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
    - return pointers
    -
    -if __name__ == "__main__":
    - import os, sys, getopt
    -
    - def usage():
    - print """
    -Usage of config_utils.py test :
    -
    - %s [options]
    -
    -Options:
    - --help (-h)
    - Displays help informations for config_utils
    -
    - --reset (-r)
    - Reset the reference result of config_utils test.
    - Use with caution. Be sure that config_utils
    - is currently working properly.
    -"""%sys.argv[0]
    -
    - # Boolean that indicate if reference result must be redefined
    - reset = False
    -
    - # Extract command options
    - try:
    - opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"])
    - except getopt.GetoptError:
    - # print help information and exit:
    - usage()
    - sys.exit(2)
    -
    - # Test each option
    - for o, a in opts:
    - if o in ("-h", "--help"):
    - usage()
    - sys.exit()
    - elif o in ("-r", "--reset"):
    - reset = True
    -
    - # Extract workspace base folder
    - base_folder = sys.path[0]
    - for i in xrange(3):
    - 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 *
    - from nodelist 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
    - try:
    - masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
    - except ValueError, message:
    - print "%s\nTest Failed!"%message
    - sys.exit()
    -
    - import pprint
    - # 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
    - if reset:
    - # Write Text into reference result file
    - testfile = open("test_config/result.txt", "w")
    - testfile.write(result)
    - testfile.close()
    -
    - print "Reset Successful!"
    - else:
    - import os
    -
    - testfile = open("test_config/result_tmp.txt", "w")
    - testfile.write(result)
    - testfile.close()
    -
    - 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 @@
    -[FileInfo]
    -CreatedBy=ESAcademy
    -ModifiedBy=ESAcademy
    -Description=PEAK MicroMod CANopenIA Generic
    -CreationTime=09:41PM
    -CreationDate=05-05-2003
    -ModificationTime=05:05PM
    -ModificationDate=03-23-2005
    -FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds
    -FileVersion=1
    -FileRevision=1
    -EDSVersion=4
    -
    -[DeviceInfo]
    -VendorName=PEAK System Technik
    -VendorNumber=0x00000175
    -ProductName=PEAK MicroMod CANopenIA Generic
    -ProductNumber=0x00100000
    -RevisionNumber=0x00010001
    -OrderCode=na
    -BaudRate_10=0
    -BaudRate_20=0
    -BaudRate_50=1
    -BaudRate_125=1
    -BaudRate_250=1
    -BaudRate_500=1
    -BaudRate_800=1
    -BaudRate_1000=1
    -SimpleBootUpMaster=0
    -SimpleBootUpSlave=1
    -Granularity=0
    -DynamicChannelsSupported=0
    -CompactPDO=0
    -GroupMessaging=0
    -NrOfRXPDO=4
    -NrOfTXPDO=4
    -LSS_Supported=0
    -
    -[DummyUsage]
    -Dummy0001=0
    -Dummy0002=0
    -Dummy0003=0
    -Dummy0004=0
    -Dummy0005=1
    -Dummy0006=1
    -Dummy0007=1
    -
    -[Comments]
    -Lines=0
    -
    -[MandatoryObjects]
    -SupportedObjects=3
    -1=0x1000
    -2=0x1001
    -3=0x1018
    -
    -[1000]
    -ParameterName=Device Type
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=ro
    -DefaultValue=0x000F0191
    -PDOMapping=0
    -
    -[1001]
    -ParameterName=Error Register
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1018]
    -ParameterName=Identity Object
    -ObjectType=0x9
    -SubNumber=4
    -
    -[1018sub0]
    -ParameterName=number of entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=3
    -PDOMapping=0
    -
    -[1018sub1]
    -ParameterName=Vendor ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=ro
    -DefaultValue=0x00000175
    -PDOMapping=0
    -
    -[1018sub2]
    -ParameterName=Product Code
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=ro
    -DefaultValue=0x00100000
    -PDOMapping=0
    -
    -[1018sub3]
    -ParameterName=Revision number
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=ro
    -DefaultValue=0x00010001
    -PDOMapping=0
    -
    -[OptionalObjects]
    -SupportedObjects=41
    -1=0x1002
    -2=0x1005
    -3=0x1008
    -4=0x1009
    -5=0x100A
    -6=0x100C
    -7=0x100D
    -8=0x1010
    -9=0x1011
    -10=0x1016
    -11=0x1017
    -12=0x1020
    -13=0x1400
    -14=0x1401
    -15=0x1402
    -16=0x1403
    -17=0x1600
    -18=0x1601
    -19=0x1602
    -20=0x1603
    -21=0x1800
    -22=0x1801
    -23=0x1802
    -24=0x1803
    -25=0x1A00
    -26=0x1A01
    -27=0x1A02
    -28=0x1A03
    -29=0x1F50
    -30=0x6000
    -31=0x6002
    -32=0x6200
    -33=0x6202
    -34=0x6206
    -35=0x6207
    -36=0x6401
    -37=0x6411
    -38=0x6423
    -39=0x6426
    -40=0x6443
    -41=0x6444
    -
    -[1002]
    -ParameterName=PEAK Status Register
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=ro
    -PDOMapping=0
    -
    -[1005]
    -ParameterName=COB-ID SYNC
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x00000080
    -PDOMapping=0
    -
    -[1008]
    -ParameterName=Manufacturer Device Name
    -ObjectType=0x7
    -DataType=0x0009
    -AccessType=const
    -PDOMapping=0
    -
    -[1009]
    -ParameterName=Manufacturer Hardware Version
    -ObjectType=0x7
    -DataType=0x0009
    -AccessType=const
    -PDOMapping=0
    -
    -[100a]
    -ParameterName=Manufacturer Software Version
    -ObjectType=0x7
    -DataType=0x0009
    -AccessType=const
    -PDOMapping=0
    -
    -[100c]
    -ParameterName=Guard Time
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[100d]
    -ParameterName=Life Time Factor
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0x00
    -PDOMapping=0
    -
    -[1010]
    -ParameterName=Store Parameter Field
    -ObjectType=0x8
    -SubNumber=2
    -
    -[1010sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[1010sub1]
    -ParameterName=Save all Parameters
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -PDOMapping=0
    -
    -[1011]
    -ParameterName=Restore Default Parameters
    -ObjectType=0x8
    -SubNumber=2
    -
    -[1011sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[1011sub1]
    -ParameterName=Restore all Default Parameters
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -PDOMapping=0
    -
    -[1016]
    -ParameterName=Consumer Heartbeat Time
    -ObjectType=0x8
    -SubNumber=4
    -
    -[1016sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=3
    -PDOMapping=0
    -LowLimit=0x1
    -
    -[1016sub1]
    -ParameterName=Consumer Heartbeat Time
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1016sub2]
    -ParameterName=Consumer Heartbeat Time
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1016sub3]
    -ParameterName=Consumer Heartbeat Time
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1017]
    -ParameterName=Producer Heartbeat Time
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1020]
    -ParameterName=Verify Configuration
    -ObjectType=0x8
    -SubNumber=3
    -
    -[1020sub0]
    -ParameterName=Number of entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=2
    -PDOMapping=0
    -
    -[1020sub1]
    -ParameterName=Configuration date
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -PDOMapping=0
    -
    -[1020sub2]
    -ParameterName=Configuration time
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -PDOMapping=0
    -
    -[1400]
    -ParameterName=Receive PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=3
    -
    -[1400sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=2
    -PDOMapping=0
    -
    -[1400sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x200
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1400sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1401]
    -ParameterName=Receive PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=3
    -
    -[1401sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=2
    -PDOMapping=0
    -
    -[1401sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x300
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1401sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1402]
    -ParameterName=Receive PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=3
    -
    -[1402sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=2
    -PDOMapping=0
    -LowLimit=0x02
    -HighLimit=0x05
    -
    -[1402sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x80000400
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1402sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1403]
    -ParameterName=Receive PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=3
    -
    -[1403sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=2
    -PDOMapping=0
    -LowLimit=0x02
    -HighLimit=0x05
    -
    -[1403sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x80000500
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1403sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1600]
    -ParameterName=Receive PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=2
    -
    -[1600sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=1
    -PDOMapping=0
    -
    -[1600sub1]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x62000108
    -PDOMapping=0
    -
    -[1601]
    -ParameterName=Receive PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=5
    -
    -[1601sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=4
    -PDOMapping=0
    -
    -[1601sub1]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64110110
    -PDOMapping=0
    -
    -[1601sub2]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64110210
    -PDOMapping=0
    -
    -[1601sub3]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64110310
    -PDOMapping=0
    -
    -[1601sub4]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64110410
    -PDOMapping=0
    -
    -[1602]
    -ParameterName=Receive PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=1
    -
    -[1602sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1603]
    -ParameterName=Receive PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=1
    -
    -[1603sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1800]
    -ParameterName=Transmit PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=5
    -
    -[1800sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=5
    -PDOMapping=0
    -LowLimit=0x02
    -HighLimit=0x05
    -
    -[1800sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x180
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1800sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1800sub3]
    -ParameterName=Inhibit Time
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0x0000
    -PDOMapping=0
    -
    -[1800sub5]
    -ParameterName=Event Timer
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1801]
    -ParameterName=Transmit PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=5
    -
    -[1801sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=5
    -PDOMapping=0
    -LowLimit=0x02
    -HighLimit=0x05
    -
    -[1801sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x280
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1801sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1801sub3]
    -ParameterName=Inhibit Time
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0x0000
    -PDOMapping=0
    -
    -[1801sub5]
    -ParameterName=Event Timer
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1802]
    -ParameterName=Transmit PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=5
    -
    -[1802sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=5
    -PDOMapping=0
    -LowLimit=0x02
    -HighLimit=0x05
    -
    -[1802sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x380
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1802sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1802sub3]
    -ParameterName=Inhibit Time
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0x0000
    -PDOMapping=0
    -
    -[1802sub5]
    -ParameterName=Event Timer
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1803]
    -ParameterName=Transmit PDO Communication Parameter
    -ObjectType=0x9
    -SubNumber=5
    -
    -[1803sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=5
    -PDOMapping=0
    -LowLimit=0x02
    -HighLimit=0x05
    -
    -[1803sub1]
    -ParameterName=COB-ID
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=$NODEID+0x80000480
    -PDOMapping=0
    -LowLimit=0x00000001
    -HighLimit=0xFFFFFFFF
    -
    -[1803sub2]
    -ParameterName=Transmission Type
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=255
    -PDOMapping=0
    -
    -[1803sub3]
    -ParameterName=Inhibit Time
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0x0000
    -PDOMapping=0
    -
    -[1803sub5]
    -ParameterName=Event Timer
    -ObjectType=0x7
    -DataType=0x0006
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1a00]
    -ParameterName=Transmit PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=2
    -
    -[1a00sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=1
    -PDOMapping=0
    -
    -[1a00sub1]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x60000108
    -PDOMapping=0
    -
    -[1a01]
    -ParameterName=Transmit PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=5
    -
    -[1a01sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=4
    -PDOMapping=0
    -
    -[1a01sub1]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010110
    -PDOMapping=0
    -
    -[1a01sub2]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010210
    -PDOMapping=0
    -
    -[1a01sub3]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010310
    -PDOMapping=0
    -
    -[1a01sub4]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010410
    -PDOMapping=0
    -
    -[1a02]
    -ParameterName=Transmit PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=5
    -
    -[1a02sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=4
    -PDOMapping=0
    -
    -[1a02sub1]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010510
    -PDOMapping=0
    -
    -[1a02sub2]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010610
    -PDOMapping=0
    -
    -[1a02sub3]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010710
    -PDOMapping=0
    -
    -[1a02sub4]
    -ParameterName=PDO Mapping Entry
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0x64010810
    -PDOMapping=0
    -
    -[1a03]
    -ParameterName=Transmit PDO Mapping Parameter
    -ObjectType=0x9
    -SubNumber=1
    -
    -[1a03sub0]
    -ParameterName=Number of Entries
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[1f50]
    -ParameterName=Download Program Data
    -ObjectType=0x8
    -SubNumber=2
    -
    -[1f50sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=3
    -PDOMapping=0
    -
    -[1f50sub3]
    -ParameterName=Download Program Data - HW Settings
    -ObjectType=0x7
    -DataType=0x000F
    -AccessType=rw
    -PDOMapping=0
    -
    -[6000]
    -ParameterName=Read Digital Input 8-bit
    -ObjectType=0x8
    -SubNumber=2
    -
    -[6000sub0]
    -ParameterName=Number of Elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[6000sub1]
    -ParameterName=DigInput8_1
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -PDOMapping=1
    -
    -[6002]
    -ParameterName=Polarity Digital Input
    -ObjectType=0x8
    -SubNumber=2
    -
    -[6002sub0]
    -ParameterName=Number of Elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[6002sub1]
    -ParameterName=Polarity8_1
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6200]
    -ParameterName=Write Digital Output 8-bit
    -ObjectType=0x8
    -SubNumber=2
    -
    -[6200sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[6200sub1]
    -ParameterName=DigOutput8_1
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rww
    -PDOMapping=1
    -
    -[6202]
    -ParameterName=Polarity Digital Output
    -ObjectType=0x8
    -SubNumber=2
    -
    -[6202sub0]
    -ParameterName=Number of Elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[6202sub1]
    -ParameterName=Polarity8_1
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6206]
    -ParameterName=Error Mode Digital Output
    -ObjectType=0x8
    -SubNumber=2
    -
    -[6206sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[6206sub1]
    -ParameterName=Error Mode 1
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6207]
    -ParameterName=Error Value Digital Output
    -ObjectType=0x8
    -SubNumber=2
    -
    -[6207sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=1
    -PDOMapping=0
    -
    -[6207sub1]
    -ParameterName=Error Value 1
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6401]
    -ParameterName=Read Analog Input 16-bit
    -ObjectType=0x8
    -SubNumber=9
    -
    -[6401sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=8
    -PDOMapping=0
    -
    -[6401sub1]
    -ParameterName=AnalogInput16_1
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6401sub2]
    -ParameterName=AnalogInput16_2
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6401sub3]
    -ParameterName=AnalogInput16_3
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6401sub4]
    -ParameterName=AnalogInput16_4
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6401sub5]
    -ParameterName=AnalogInput16_5
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6401sub6]
    -ParameterName=AnalogInput16_6
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6401sub7]
    -ParameterName=AnalogInput16_7
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6401sub8]
    -ParameterName=AnalogInput16_8
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=ro
    -PDOMapping=1
    -
    -[6411]
    -ParameterName=Write Analog Output 16-bit
    -ObjectType=0x8
    -SubNumber=5
    -
    -[6411sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=4
    -PDOMapping=0
    -
    -[6411sub1]
    -ParameterName=AnalogOutput16_1
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=rww
    -PDOMapping=1
    -
    -[6411sub2]
    -ParameterName=AnalogOutput16_2
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=rww
    -PDOMapping=1
    -
    -[6411sub3]
    -ParameterName=AnalogOutput16_3
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=rww
    -PDOMapping=1
    -
    -[6411sub4]
    -ParameterName=AnalogOutput16_4
    -ObjectType=0x7
    -DataType=0x0003
    -AccessType=rww
    -PDOMapping=1
    -
    -[6423]
    -ParameterName=Analog Input Global Interrupt
    -ObjectType=0x7
    -DataType=0x0001
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426]
    -ParameterName=Analog Input Interrupt Delta
    -ObjectType=0x8
    -SubNumber=9
    -
    -[6426sub0]
    -ParameterName=NrOfObjects
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=8
    -PDOMapping=0
    -
    -[6426sub1]
    -ParameterName=Analog Input Delta 1
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426sub2]
    -ParameterName=Analog Input Delta 2
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426sub3]
    -ParameterName=Analog Input Delta 3
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426sub4]
    -ParameterName=Analog Input Delta 4
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426sub5]
    -ParameterName=Analog Input Delta 5
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426sub6]
    -ParameterName=Analog Input Delta 6
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426sub7]
    -ParameterName=Analog Input Delta 7
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6426sub8]
    -ParameterName=Analog Input Delta 8
    -ObjectType=0x7
    -DataType=0x0007
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6443]
    -ParameterName=Error Mode Analog Output
    -ObjectType=0x8
    -SubNumber=5
    -
    -[6443sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=4
    -PDOMapping=0
    -
    -[6443sub1]
    -ParameterName=Error Mode 1
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6443sub2]
    -ParameterName=Error Mode 2
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6443sub3]
    -ParameterName=Error Mode 3
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6443sub4]
    -ParameterName=Error Mode 4
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6444]
    -ParameterName=Error Value Analog Output
    -ObjectType=0x8
    -SubNumber=5
    -
    -[6444sub0]
    -ParameterName=Number of elements
    -ObjectType=0x7
    -DataType=0x0005
    -AccessType=ro
    -DefaultValue=4
    -PDOMapping=0
    -
    -[6444sub1]
    -ParameterName=Error Value 1
    -ObjectType=0x7
    -DataType=0x0004
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6444sub2]
    -ParameterName=Error Value 2
    -ObjectType=0x7
    -DataType=0x0004
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6444sub3]
    -ParameterName=Error Value 3
    -ObjectType=0x7
    -DataType=0x0004
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[6444sub4]
    -ParameterName=Error Value 4
    -ObjectType=0x7
    -DataType=0x0004
    -AccessType=rw
    -DefaultValue=0
    -PDOMapping=0
    -
    -[ManufacturerObjects]
    -SupportedObjects=0
    --- 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 @@
    -<?xml version="1.0"?>
    -<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
    -<PyObject module="node" class="Node" id="148584620">
    -<attr name="Profile" type="dict" id="148589396" >
    -</attr>
    -<attr name="Description" type="string" value="" />
    -<attr name="Dictionary" type="dict" id="148592132" >
    - <entry>
    - <key type="numeric" value="4096" />
    - <val type="numeric" value="302" />
    - </entry>
    - <entry>
    - <key type="numeric" value="4097" />
    - <val type="numeric" value="0" />
    - </entry>
    - <entry>
    - <key type="numeric" value="6144" />
    - <val type="list" id="148585004" >
    - <item type="string" value="{True:&quot;$NODEID+0x%X80&quot;%(base+1),False:0x80000000}[base&lt;4]" />
    - <item type="numeric" value="0" />
    - <item type="numeric" value="0" />
    - <item type="numeric" value="0" />
    - <item type="numeric" value="0" />
    - </val>
    - </entry>
    - <entry>
    - <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" />
    - </val>
    - </entry>
    - <entry>
    - <key type="numeric" value="4101" />
    - <val type="numeric" value="1073741952" />
    - </entry>
    - <entry>
    - <key type="numeric" value="4102" />
    - <val type="numeric" value="50000" />
    - </entry>
    - <entry>
    - <key type="numeric" value="8192" />
    - <val type="numeric" value="0" />
    - </entry>
    - <entry>
    - <key type="numeric" value="6656" />
    - <val type="list" id="148585228" >
    - <item type="numeric" value="268501000" />
    - </val>
    - </entry>
    - <entry>
    - <key type="numeric" value="5632" />
    - <val type="list" id="148585036" >
    - <item type="numeric" value="536870920" />
    - </val>
    - </entry>
    - <entry>
    - <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" />
    - </val>
    - </entry>
    - <entry>
    - <key type="numeric" value="4118" />
    - <val type="list" id="148585100" >
    - <item type="numeric" value="4195804" />
    - </val>
    - </entry>
    -</attr>
    -<attr name="SpecificMenu" type="list" id="148584044" >
    -</attr>
    -<attr name="ParamsDictionary" type="dict" id="148592268" >
    -</attr>
    -<attr name="UserMapping" type="dict" id="148592404" >
    - <entry>
    - <key type="numeric" value="8192" />
    - <val type="dict" id="148592540" >
    - <entry>
    - <key type="string" value="need" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="values" />
    - <val type="list" id="148585868" >
    - <item type="dict" id="148592676" >
    - <entry>
    - <key type="string" value="access" />
    - <val type="string" value="rw" />
    - </entry>
    - <entry>
    - <key type="string" value="pdo" />
    - <val type="True" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="type" />
    - <val type="numeric" value="5" />
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string">Read Inputs</val>
    - </entry>
    - </item>
    - </val>
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string">Read Inputs</val>
    - </entry>
    - <entry>
    - <key type="string" value="struct" />
    - <val type="numeric" value="1" />
    - </entry>
    - </val>
    - </entry>
    -</attr>
    -<attr name="DS302" type="dict" id="148592812" >
    - <entry>
    - <key type="numeric" value="7968" />
    - <val type="dict" id="148592948" >
    - <entry>
    - <key type="string" value="need" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="values" />
    - <val type="list" id="148584684" >
    - <item type="dict" id="148593084" >
    - <entry>
    - <key type="string" value="access" />
    - <val type="string" value="ro" />
    - </entry>
    - <entry>
    - <key type="string" value="pdo" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="type" />
    - <val type="numeric" value="5" />
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Number of Entries" />
    - </entry>
    - </item>
    - <item type="dict" id="148593220" >
    - <entry>
    - <key type="string" value="access" />
    - <val type="string" value="rw" />
    - </entry>
    - <entry>
    - <key type="string" value="pdo" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="type" />
    - <val type="numeric" value="15" />
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Store DCF for node %d[(sub)]" />
    - </entry>
    - <entry>
    - <key type="string" value="nbmax" />
    - <val type="numeric" value="127" />
    - </entry>
    - </item>
    - </val>
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Store DCF" />
    - </entry>
    - <entry>
    - <key type="string" value="struct" />
    - <val type="numeric" value="7" />
    - </entry>
    - </val>
    - </entry>
    - <entry>
    - <key type="numeric" value="7969" />
    - <val type="dict" id="148593356" >
    - <entry>
    - <key type="string" value="need" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="values" />
    - <val type="list" id="148585516" >
    - <item type="dict" id="148593492" >
    - <entry>
    - <key type="string" value="access" />
    - <val type="string" value="ro" />
    - </entry>
    - <entry>
    - <key type="string" value="pdo" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="type" />
    - <val type="numeric" value="5" />
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Number of Entries" />
    - </entry>
    - </item>
    - <item type="dict" id="148593628" >
    - <entry>
    - <key type="string" value="access" />
    - <val type="string" value="rw" />
    - </entry>
    - <entry>
    - <key type="string" value="pdo" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="type" />
    - <val type="numeric" value="2" />
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Storage Format for Node %d[(sub)]" />
    - </entry>
    - <entry>
    - <key type="string" value="nbmax" />
    - <val type="numeric" value="127" />
    - </entry>
    - </item>
    - </val>
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Storage Format" />
    - </entry>
    - <entry>
    - <key type="string" value="struct" />
    - <val type="numeric" value="7" />
    - </entry>
    - </val>
    - </entry>
    - <entry>
    - <key type="numeric" value="7970" />
    - <val type="dict" id="148593764" >
    - <entry>
    - <key type="string" value="need" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="values" />
    - <val type="list" id="148594956" >
    - <item type="dict" id="148593900" >
    - <entry>
    - <key type="string" value="access" />
    - <val type="string" value="ro" />
    - </entry>
    - <entry>
    - <key type="string" value="pdo" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="type" />
    - <val type="numeric" value="5" />
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Number of Entries" />
    - </entry>
    - </item>
    - <item type="dict" id="148594036" >
    - <entry>
    - <key type="string" value="access" />
    - <val type="string" value="rw" />
    - </entry>
    - <entry>
    - <key type="string" value="pdo" />
    - <val type="False" value="" />
    - </entry>
    - <entry>
    - <key type="string" value="type" />
    - <val type="numeric" value="15" />
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Concise DCF for Node %d[(sub)]" />
    - </entry>
    - <entry>
    - <key type="string" value="nbmax" />
    - <val type="numeric" value="127" />
    - </entry>
    - </item>
    - </val>
    - </entry>
    - <entry>
    - <key type="string" value="name" />
    - <val type="string" value="Concise DCF" />
    - </entry>
    - <entry>
    - <key type="string" value="struct" />
    - <val type="numeric" value="7" />
    - </entry>
    - </val>
    - </entry>
    -</attr>
    -<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>
    -</PyObject>
    --- 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 @@
    -[TOPOLOGY]
    -NetName=None
    -Nodes=0x01
    -Node64Present=0x01
    -Node64Name=micromod
    -Node64DCFName=PEAK MicroMod.eds
    -EDSBaseName=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 @@
    -1000 (Device Type): 12E
    -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 (Identity):
    -1018 01 (Vendor ID): 0
    -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 (Concise DCF):
    -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):
    -2000 (Read Inputs): 0
    -2240 (beremiz__IB0_1_64):
    -2240 01 (24576_1): 0
    -2240 02 (24578_1): 0
    -2340 (beremiz__IW0_1_64):
    -2340 01 (25601_2): 0
    -2340 02 (25601_3): 0
    -2440 (beremiz__ID0_1_64):
    -2440 01 (25638_2): 0
    -2440 02 (25638_3): 0
    -2440 03 (25638_4): 0
    -2440 04 (25638_1): 0
    -4340 (beremiz__QW0_1_64):
    -4340 01 (25617_1): 0
    -
    -********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 @@
    -import wx, wx.grid
    -import wx.stc as stc
    -import keyword
    -
    -from controls import EditorPanel
    -
    -if wx.Platform == '__WXMSW__':
    - faces = { 'times': 'Times New Roman',
    - 'mono' : 'Courier New',
    - 'helv' : 'Arial',
    - 'other': 'Comic Sans MS',
    - 'size' : 10,
    - 'size2': 8,
    - }
    -elif wx.Platform == '__WXMAC__':
    - faces = { 'times': 'Times New Roman',
    - 'mono' : 'Monaco',
    - 'helv' : 'Arial',
    - 'other': 'Comic Sans MS',
    - 'size' : 12,
    - 'size2': 10,
    - }
    -else:
    - faces = { 'times': 'Times',
    - 'mono' : 'Courier',
    - 'helv' : 'Helvetica',
    - 'other': 'new century schoolbook',
    - 'size' : 12,
    - 'size2': 10,
    - }
    -
    -[ID_PYTHONEDITOR,
    -] = [wx.NewId() for _init_ctrls in range(1)]
    -
    -def GetCursorPos(old, new):
    - old_length = len(old)
    - new_length = len(new)
    - common_length = min(old_length, new_length)
    - i = 0
    - for i in xrange(common_length):
    - if old[i] != new[i]:
    - break
    - if old_length < new_length:
    - if common_length > 0 and old[i] != new[i]:
    - return i + new_length - old_length
    - else:
    - 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]:
    - return i
    - else:
    - return i + 1
    - else:
    - return None
    -
    -class PythonEditor(EditorPanel):
    -
    - fold_symbols = 3
    -
    - 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)
    -
    - # Global default style
    - 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')
    - else:
    - 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')
    - # Highlighted brace
    - self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
    - # Unmatched brace
    - self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
    - # Indentation guide
    - self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
    -
    - # Python styles
    - self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
    - # Comments
    - self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
    - self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
    - # Numbers
    - 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')
    - # Keywords
    - self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
    - # Triple quotes
    - self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
    - self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
    - # Class names
    - self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
    - # Function names
    - self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
    - # Operators
    - 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')
    -
    - # Caret color
    - self.Editor.SetCaretForeground("BLUE")
    - # Selection background
    - 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!
    - # White space
    - 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
    - # edit them that way.
    - 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)))
    -
    - def __del__(self):
    - self.Controler.OnCloseEditor(self)
    -
    - def GetTitle(self):
    - fullname = self.Controler.CTNFullName()
    - if not self.Controler.PythonIsSaved():
    - return "~%s~" % fullname
    - return fullname
    -
    - def GetBufferState(self):
    - return self.Controler.GetBufferState()
    -
    - def Undo(self):
    - self.Controler.LoadPrevious()
    - self.RefreshView()
    -
    - def Redo(self):
    - self.Controler.LoadNext()
    - self.RefreshView()
    -
    - def HasNoModel(self):
    - return False
    -
    - 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:
    - self.StartBuffering()
    - elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
    - self.Controler.EndBuffering()
    - self.StartBuffering()
    - self.CurrentAction = ("Add", event.GetPosition())
    - wx.CallAfter(self.RefreshModel)
    - elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
    - if self.CurrentAction == None:
    - self.StartBuffering()
    - elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
    - self.Controler.EndBuffering()
    - self.StartBuffering()
    - self.CurrentAction = ("Delete", event.GetPosition())
    - wx.CallAfter(self.RefreshModel)
    - event.Skip()
    -
    - def OnDoDrop(self, event):
    - self.ResetBuffer()
    - wx.CallAfter(self.RefreshModel)
    - event.Skip()
    -
    - # 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()
    -
    - def ResetBuffer(self):
    - if self.CurrentAction != None:
    - self.Controler.EndBuffering()
    - self.CurrentAction = None
    -
    - def RefreshView(self):
    - self.ResetBuffer()
    - 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)
    - else:
    - 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()
    -
    - # Tips
    - if event.ShiftDown():
    - pass
    -## 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)')
    - # Code completion
    - else:
    - 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]))
    - else:
    - event.Skip()
    -
    - def OnKillFocus(self, event):
    - self.Editor.AutoCompCancel()
    - event.Skip()
    -
    - def OnUpdateUI(self, evt):
    - # check for matching braces
    - braceAtCaret = -1
    - braceOpposite = -1
    - charBefore = None
    - caretPos = self.Editor.GetCurrentPos()
    -
    - if caretPos > 0:
    - charBefore = self.Editor.GetCharAt(caretPos - 1)
    - styleBefore = self.Editor.GetStyleAt(caretPos - 1)
    -
    - # check before
    - if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
    - braceAtCaret = caretPos - 1
    -
    - # check after
    - if braceAtCaret < 0:
    - charAfter = self.Editor.GetCharAt(caretPos)
    - styleAfter = self.Editor.GetStyleAt(caretPos)
    -
    - if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
    - braceAtCaret = caretPos
    -
    - if braceAtCaret >= 0:
    - braceOpposite = self.Editor.BraceMatch(braceAtCaret)
    -
    - if braceAtCaret != -1 and braceOpposite == -1:
    - self.Editor.BraceBadLight(braceAtCaret)
    - else:
    - self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
    - #pt = self.Editor.PointFromPosition(braceOpposite)
    - #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
    - #print pt
    - #self.Editor.Refresh(False)
    -
    -
    - def OnMarginClick(self, evt):
    - # fold and unfold as needed
    - if evt.GetMargin() == 2:
    - if evt.GetShift() and evt.GetControl():
    - self.FoldAll()
    - else:
    - lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
    -
    - if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
    - if evt.GetShift():
    - self.Editor.SetFoldExpanded(lineClicked, True)
    - self.Expand(lineClicked, True, True, 1)
    - elif evt.GetControl():
    - if self.Editor.GetFoldExpanded(lineClicked):
    - self.Editor.SetFoldExpanded(lineClicked, False)
    - self.Expand(lineClicked, False, True, 0)
    - else:
    - self.Editor.SetFoldExpanded(lineClicked, True)
    - self.Expand(lineClicked, True, True, 100)
    - else:
    - self.Editor.ToggleFold(lineClicked)
    -
    -
    - def FoldAll(self):
    - lineCount = self.Editor.GetLineCount()
    - expanding = True
    -
    - # 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)
    - break
    -
    - lineNum = 0
    -
    - while lineNum < lineCount:
    - level = self.Editor.GetFoldLevel(lineNum)
    - if level & stc.STC_FOLDLEVELHEADERFLAG and \
    - (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
    -
    - if expanding:
    - self.Editor.SetFoldExpanded(lineNum, True)
    - lineNum = self.Expand(lineNum, True)
    - lineNum = lineNum - 1
    - else:
    - lastChild = self.Editor.GetLastChild(lineNum, -1)
    - self.Editor.SetFoldExpanded(lineNum, False)
    -
    - if lastChild > lineNum:
    - self.Editor.HideLines(lineNum+1, lastChild)
    -
    - lineNum = lineNum + 1
    -
    -
    -
    - def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
    - lastChild = self.Editor.GetLastChild(line, level)
    - line = line + 1
    -
    - while line <= lastChild:
    - if force:
    - if visLevels > 0:
    - self.Editor.ShowLines(line, line)
    - else:
    - self.Editor.HideLines(line, line)
    - else:
    - if doExpand:
    - self.Editor.ShowLines(line, line)
    -
    - if level == -1:
    - level = self.Editor.GetFoldLevel(line)
    -
    - if level & stc.STC_FOLDLEVELHEADERFLAG:
    - if force:
    - if visLevels > 1:
    - self.Editor.SetFoldExpanded(line, True)
    - else:
    - self.Editor.SetFoldExpanded(line, False)
    -
    - line = self.Expand(line, doExpand, force, visLevels-1)
    -
    - else:
    - if doExpand and self.Editor.GetFoldExpanded(line):
    - line = self.Expand(line, True, force, visLevels-1)
    - else:
    - line = self.Expand(line, False, force, visLevels-1)
    - else:
    - line = line + 1
    -
    - return line
    -
    - def Cut(self):
    - self.ResetBuffer()
    - self.DisableEvents = True
    - self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
    - self.DisableEvents = False
    - self.RefreshModel()
    - self.RefreshBuffer()
    -
    - def Copy(self):
    - self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
    -
    - def Paste(self):
    - self.ResetBuffer()
    - self.DisableEvents = True
    - self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
    - self.DisableEvents = False
    - self.RefreshModel()
    - self.RefreshBuffer()
    --- 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 @@
    -from python import *
    --- 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("__")]
    -
    -helps = []
    -for name in __all__:
    - helpfilename = path.join(_base_path, name, "README")
    - if path.isfile(helpfilename):
    - helps.append(open(helpfilename).readline().strip())
    - else:
    - helps.append(name)
    --- 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 @@
    -SVGUI HMI
    \ 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 @@
    -from svgui import *
    --- 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 @@
    -// import Nevow.Athena
    -// import Divmod.Base
    -
    -function updateAttr(id, param, value) {
    - Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value);
    -}
    -
    -var svguiWidgets = new Array();
    -
    -var currentObject = null;
    -function setCurrentObject(obj) {
    - currentObject = obj;
    -}
    -function isCurrentObject(obj) {
    - return currentObject == obj;
    -}
    -
    -function getSVGElementById(id) {
    - return document.getElementById(id);
    -}
    -
    -function blockSVGElementDrag(element) {
    - element.addEventListener("draggesture", function(event){event.stopPropagation()}, true);
    -}
    -
    -LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget');
    -LiveSVGPage.LiveSVGWidget.methods(
    -
    - function handleEvent(self, evt) {
    - if (currentObject != null) {
    - currentObject.handleEvent(evt);
    - }
    - },
    -
    - function receiveData(self, data){
    - dataReceived = json_parse(data);
    - gadget = svguiWidgets[dataReceived.id]
    - if (gadget) {
    - gadget.updateValues(json_parse(dataReceived.kwargs));
    - }
    - //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState);
    - },
    -
    - function init(self, arg1){
    - //console.log("Object received : " + arg1);
    - for (ind in arg1) {
    - gad = json_parse(arg1[ind]);
    - args = json_parse(gad.kwargs);
    - gadget = new svguilib[gad.__class__](self, gad.id, args);
    - svguiWidgets[gadget.id]=gadget;
    - //console.log('GADGET :' + gadget);
    - }
    - var elements = document.getElementsByTagName("svg");
    - for (var i = 0; i < elements.length; i++) {
    - elements[i].addEventListener("mouseup", self, false);
    - }
    - //console.log("SVGUIWIDGETS : " + svguiWidgets);
    - }
    -);
    --- 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"
    - productName="Beremiz"
    - productVersion="0.0"
    - creationDateTime="2008-12-14T16:53:26"/>
    - <contentHeader name="Beremiz non-standard POUs library"
    - modificationDateTime="2009-08-12T15:35:33">
    - <coordinateInfo>
    - <fbd>
    - <scaling x="0" y="0"/>
    - </fbd>
    - <ld>
    - <scaling x="0" y="0"/>
    - </ld>
    - <sfc>
    - <scaling x="0" y="0"/>
    - </sfc>
    - </coordinateInfo>
    - </contentHeader>
    - <types>
    - <dataTypes/>
    - <pous>
    - <pou name="GetBoolString" pouType="functionBlock">
    - <interface>
    - <inputVars>
    - <variable name="VALUE">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - </inputVars>
    - <outputVars>
    - <variable name="CODE">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </outputVars>
    - </interface>
    - <body>
    - <ST>
    -<![CDATA[IF VALUE THEN
    - CODE := 'True';
    -ELSE
    - CODE := 'False';
    -END_IF;]]>
    - </ST>
    - </body>
    - </pou>
    - <pou name="TextCtrl" pouType="functionBlock">
    - <interface>
    - <localVars>
    - <variable name="ID">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </localVars>
    - <inputVars>
    - <variable name="back_id">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="set_text">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="text">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </inputVars>
    - <localVars>
    - <variable name="SVGUI_TEXTCTRL">
    - <type>
    - <derived name="python_eval"/>
    - </type>
    - </variable>
    - <variable name="setstate_Command">
    - <type>
    - <derived name="python_eval"/>
    - </type>
    - </variable>
    - </localVars>
    - </interface>
    - <body>
    - <FBD>
    - <block localId="1" width="193" height="160" typeName="CONCAT">
    - <position x="626" y="122"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="43"/>
    - <connection refLocalId="2">
    - <position x="626" y="165"/>
    - <position x="535" y="165"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="89"/>
    - <connection refLocalId="3">
    - <position x="626" y="211"/>
    - <position x="535" y="211"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN3">
    - <connectionPointIn>
    - <relPosition x="0" y="135"/>
    - <connection refLocalId="6">
    - <position x="626" y="257"/>
    - <position x="532" y="257"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="193" y="43"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="2" height="30" width="460">
    - <position x="75" y="150"/>
    - <connectionPointOut>
    - <relPosition x="460" y="15"/>
    - </connectionPointOut>
    - <expression>'createSVGUIControl("textControl", back_id="'</expression>
    - </inVariable>
    - <inVariable localId="3" height="35" width="85">
    - <position x="450" y="196"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>back_id</expression>
    - </inVariable>
    - <inVariable localId="6" height="30" width="50">
    - <position x="482" y="242"/>
    - <connectionPointOut>
    - <relPosition x="50" y="15"/>
    - </connectionPointOut>
    - <expression>'")'</expression>
    - </inVariable>
    - <block localId="7" width="125" height="115" typeName="python_eval" instanceName="SVGUI_TEXTCTRL">
    - <position x="909" y="75"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="90"/>
    - <connection refLocalId="1" formalParameter="OUT">
    - <position x="909" y="165"/>
    - <position x="819" y="165"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="45"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="90"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="9" height="30" width="70">
    - <position x="799" y="70"/>
    - <connectionPointOut>
    - <relPosition x="70" y="15"/>
    - </connectionPointOut>
    - <expression>BOOL#1</expression>
    - </inVariable>
    - <outVariable localId="10" height="30" width="30">
    - <position x="1094" y="150"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="7" formalParameter="RESULT">
    - <position x="1094" y="165"/>
    - <position x="1034" y="165"/>
    - </connection>
    - </connectionPointIn>
    - <expression>ID</expression>
    - </outVariable>
    - <connector name="CREATED" localId="11" height="30" width="110">
    - <position x="1096" y="105"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="7" formalParameter="ACK">
    - <position x="1096" y="120"/>
    - <position x="1034" y="120"/>
    - </connection>
    - </connectionPointIn>
    - </connector>
    - <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
    - <position x="957" y="472"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="12" formalParameter="OUT">
    - <position x="957" y="582"/>
    - <position x="822" y="582"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="50"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="110"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <continuation name="CREATED" localId="5" height="30" width="110">
    - <position x="589" y="429"/>
    - <connectionPointOut>
    - <relPosition x="110" y="15"/>
    - </connectionPointOut>
    - </continuation>
    - <block localId="12" width="186" height="288" typeName="CONCAT">
    - <position x="636" y="536"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="46"/>
    - <connection refLocalId="14">
    - <position x="636" y="582"/>
    - <position x="526" y="582"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="99"/>
    - <connection refLocalId="8">
    - <position x="636" y="635"/>
    - <position x="526" y="635"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN3">
    - <connectionPointIn>
    - <relPosition x="0" y="152"/>
    - <connection refLocalId="15">
    - <position x="636" y="688"/>
    - <position x="527" y="688"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN4">
    - <connectionPointIn>
    - <relPosition x="0" y="205"/>
    - <connection refLocalId="32">
    - <position x="636" y="741"/>
    - <position x="528" y="741"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN5">
    - <connectionPointIn>
    - <relPosition x="0" y="258"/>
    - <connection refLocalId="16">
    - <position x="636" y="794"/>
    - <position x="528" y="794"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="186" y="46"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="8" height="30" width="53">
    - <position x="473" y="620"/>
    - <connectionPointOut>
    - <relPosition x="53" y="15"/>
    - </connectionPointOut>
    - <expression>ID</expression>
    - </inVariable>
    - <inVariable localId="13" height="35" width="100">
    - <position x="599" y="469"/>
    - <connectionPointOut>
    - <relPosition x="100" y="17"/>
    - </connectionPointOut>
    - <expression>set_text</expression>
    - </inVariable>
    - <inVariable localId="14" height="30" width="120">
    - <position x="406" y="567"/>
    - <connectionPointOut>
    - <relPosition x="120" y="15"/>
    - </connectionPointOut>
    - <expression>'setAttr('</expression>
    - </inVariable>
    - <inVariable localId="15" height="30" width="122">
    - <position x="405" y="673"/>
    - <connectionPointOut>
    - <relPosition x="122" y="15"/>
    - </connectionPointOut>
    - <expression>',"text","'</expression>
    - </inVariable>
    - <inVariable localId="16" height="30" width="50">
    - <position x="478" y="779"/>
    - <connectionPointOut>
    - <relPosition x="50" y="15"/>
    - </connectionPointOut>
    - <expression>'")'</expression>
    - </inVariable>
    - <block localId="31" width="75" height="105" typeName="AND">
    - <position x="782" y="403"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="41"/>
    - <connection refLocalId="5">
    - <position x="782" y="444"/>
    - <position x="699" y="444"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="83"/>
    - <connection refLocalId="13">
    - <position x="782" y="486"/>
    - <position x="699" y="486"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="75" y="41"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="32" height="30" width="90">
    - <position x="438" y="726"/>
    - <connectionPointOut>
    - <relPosition x="90" y="15"/>
    - </connectionPointOut>
    - <expression>text</expression>
    - </inVariable>
    - </FBD>
    - </body>
    - </pou>
    - <pou name="Button" pouType="functionBlock">
    - <interface>
    - <localVars>
    - <variable name="ID">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </localVars>
    - <inputVars>
    - <variable name="back_id">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="sele_id">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="toggle">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="set_state">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="state_in">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - </inputVars>
    - <outputVars>
    - <variable name="state_out">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - </outputVars>
    - <localVars>
    - <variable name="init_Command">
    - <type>
    - <derived name="python_eval"/>
    - </type>
    - </variable>
    - <variable name="GetButtonState">
    - <type>
    - <derived name="GetBoolString"/>
    - </type>
    - </variable>
    - <variable name="setstate_Command">
    - <type>
    - <derived name="python_eval"/>
    - </type>
    - </variable>
    - <variable name="getstate_Command">
    - <type>
    - <derived name="python_poll"/>
    - </type>
    - </variable>
    - <variable name="GetButtonToggle">
    - <type>
    - <derived name="GetBoolString"/>
    - </type>
    - </variable>
    - </localVars>
    - </interface>
    - <body>
    - <FBD>
    - <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
    - <position x="838" y="32"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <relPosition x="0" y="50"/>
    - <connection refLocalId="10">
    - <position x="838" y="82"/>
    - <position x="781" y="82"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="2" formalParameter="OUT">
    - <position x="838" y="142"/>
    - <position x="641" y="142"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="50"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="110"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <block localId="2" width="150" height="442" typeName="CONCAT">
    - <position x="491" y="92"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="50"/>
    - <connection refLocalId="3">
    - <position x="491" y="142"/>
    - <position x="433" y="142"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="11">
    - <position x="491" y="202"/>
    - <position x="431" y="202"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN3">
    - <connectionPointIn>
    - <relPosition x="0" y="170"/>
    - <connection refLocalId="5">
    - <position x="491" y="262"/>
    - <position x="431" y="262"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN4">
    - <connectionPointIn>
    - <relPosition x="0" y="230"/>
    - <connection refLocalId="12">
    - <position x="491" y="322"/>
    - <position x="430" y="322"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN5">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN6">
    - <connectionPointIn>
    - <relPosition x="0" y="350"/>
    - <connection refLocalId="24" formalParameter="CODE">
    - <position x="491" y="442"/>
    - <position x="429" y="442"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN7">
    - <connectionPointIn>
    - <relPosition x="0" y="410"/>
    - <connection refLocalId="9">
    - <position x="491" y="502"/>
    - <position x="430" y="502"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="150" y="50"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="3" height="30" width="400">
    - <position x="33" y="127"/>
    - <connectionPointOut>
    - <relPosition x="400" y="15"/>
    - </connectionPointOut>
    - <expression>'createSVGUIControl("button",back_id="'</expression>
    - </inVariable>
    - <inVariable localId="5" height="30" width="140">
    - <position x="291" y="247"/>
    - <connectionPointOut>
    - <relPosition x="140" y="15"/>
    - </connectionPointOut>
    - <expression>'",sele_id="'</expression>
    - </inVariable>
    - <inVariable localId="9" height="30" width="180">
    - <position x="250" y="487"/>
    - <connectionPointOut>
    - <relPosition x="180" y="15"/>
    - </connectionPointOut>
    - <expression>',active=True)'</expression>
    - </inVariable>
    - <inVariable localId="10" height="30" width="70">
    - <position x="711" y="67"/>
    - <connectionPointOut>
    - <relPosition x="70" y="15"/>
    - </connectionPointOut>
    - <expression>BOOL#1</expression>
    - </inVariable>
    - <inVariable localId="11" height="35" width="85">
    - <position x="346" y="187"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>back_id</expression>
    - </inVariable>
    - <inVariable localId="12" height="35" width="85">
    - <position x="345" y="307"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>sele_id</expression>
    - </inVariable>
    - <inVariable localId="13" height="35" width="100">
    - <position x="452" y="639"/>
    - <connectionPointOut>
    - <relPosition x="100" y="15"/>
    - </connectionPointOut>
    - <expression>set_state</expression>
    - </inVariable>
    - <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonState">
    - <position x="239" y="897"/>
    - <inputVariables>
    - <variable formalParameter="VALUE">
    - <connectionPointIn>
    - <relPosition x="0" y="30"/>
    - <connection refLocalId="32">
    - <position x="239" y="927"/>
    - <position x="181" y="927"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="CODE">
    - <connectionPointOut>
    - <relPosition x="140" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <outVariable localId="29" height="30" width="53">
    - <position x="1015" y="127"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="1" formalParameter="RESULT">
    - <position x="1015" y="142"/>
    - <position x="963" y="142"/>
    - </connection>
    - </connectionPointIn>
    - <expression>ID</expression>
    - </outVariable>
    - <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
    - <position x="810" y="640"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="7" formalParameter="OUT">
    - <position x="810" y="750"/>
    - <position x="643" y="750"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="50"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="110"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <connector name="CREATED" localId="30" height="30" width="110">
    - <position x="1014" y="67"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="1" formalParameter="ACK">
    - <position x="1014" y="82"/>
    - <position x="963" y="82"/>
    - </connection>
    - </connectionPointIn>
    - </connector>
    - <continuation name="CREATED" localId="6" height="30" width="110">
    - <position x="442" y="597"/>
    - <connectionPointOut>
    - <relPosition x="110" y="15"/>
    - </connectionPointOut>
    - </continuation>
    - <block localId="31" width="75" height="105" typeName="AND">
    - <position x="635" y="571"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="41"/>
    - <connection refLocalId="6">
    - <position x="635" y="612"/>
    - <position x="552" y="612"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="83"/>
    - <connection refLocalId="13">
    - <position x="635" y="654"/>
    - <position x="552" y="654"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="75" y="41"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="32" height="30" width="90">
    - <position x="91" y="912"/>
    - <connectionPointOut>
    - <relPosition x="90" y="15"/>
    - </connectionPointOut>
    - <expression>state_in</expression>
    - </inVariable>
    - <outVariable localId="33" height="30" width="100">
    - <position x="1334" y="1184"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="26" formalParameter="OUT">
    - <position x="1334" y="1199"/>
    - <position x="1286" y="1199"/>
    - </connection>
    - </connectionPointIn>
    - <expression>state_out</expression>
    - </outVariable>
    - <block localId="7" width="150" height="319" typeName="CONCAT">
    - <position x="493" y="701"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="49"/>
    - <connection refLocalId="14">
    - <position x="493" y="750"/>
    - <position x="379" y="750"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN3">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN4">
    - <connectionPointIn>
    - <relPosition x="0" y="226"/>
    - <connection refLocalId="28" formalParameter="CODE">
    - <position x="493" y="927"/>
    - <position x="379" y="927"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN5">
    - <connectionPointIn>
    - <relPosition x="0" y="285"/>
    - <connection refLocalId="16">
    - <position x="493" y="986"/>
    - <position x="377" y="986"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="150" y="49"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="8" height="30" width="53">
    - <position x="326" y="788"/>
    - <connectionPointOut>
    - <relPosition x="53" y="15"/>
    - </connectionPointOut>
    - <expression>ID</expression>
    - </inVariable>
    - <inVariable localId="14" height="30" width="120">
    - <position x="259" y="735"/>
    - <connectionPointOut>
    - <relPosition x="120" y="15"/>
    - </connectionPointOut>
    - <expression>'setAttr('</expression>
    - </inVariable>
    - <inVariable localId="15" height="30" width="122">
    - <position x="257" y="840"/>
    - <connectionPointOut>
    - <relPosition x="122" y="15"/>
    - </connectionPointOut>
    - <expression>',"state",'</expression>
    - </inVariable>
    - <inVariable localId="16" height="30" width="41">
    - <position x="336" y="971"/>
    - <connectionPointOut>
    - <relPosition x="41" y="15"/>
    - </connectionPointOut>
    - <expression>')'</expression>
    - </inVariable>
    - <block localId="17" width="125" height="140" typeName="python_poll" instanceName="getstate_Command">
    - <position x="801" y="1089"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="22" formalParameter="OUT">
    - <position x="801" y="1199"/>
    - <position x="643" y="1199"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="50"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="110"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <block localId="25" width="145" height="45" typeName="STRING_TO_INT">
    - <position x="966" y="1169"/>
    - <inputVariables>
    - <variable formalParameter="IN">
    - <connectionPointIn>
    - <relPosition x="0" y="30"/>
    - <connection refLocalId="17" formalParameter="RESULT">
    - <position x="966" y="1199"/>
    - <position x="926" y="1199"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="145" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <block localId="26" width="125" height="45" typeName="INT_TO_BOOL">
    - <position x="1161" y="1169"/>
    - <inputVariables>
    - <variable formalParameter="IN">
    - <connectionPointIn>
    - <relPosition x="0" y="30"/>
    - <connection refLocalId="25" formalParameter="OUT">
    - <position x="1161" y="1199"/>
    - <position x="1111" y="1199"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="125" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <continuation name="CREATED" localId="18" height="30" width="110">
    - <position x="610" y="1084"/>
    - <connectionPointOut>
    - <relPosition x="110" y="15"/>
    - </connectionPointOut>
    - </continuation>
    - <inVariable localId="19" height="30" width="53">
    - <position x="383" y="1238"/>
    - <connectionPointOut>
    - <relPosition x="53" y="15"/>
    - </connectionPointOut>
    - <expression>ID</expression>
    - </inVariable>
    - <inVariable localId="20" height="30" width="150">
    - <position x="286" y="1184"/>
    - <connectionPointOut>
    - <relPosition x="150" y="15"/>
    - </connectionPointOut>
    - <expression>'int(getAttr('</expression>
    - </inVariable>
    - <inVariable localId="21" height="30" width="190">
    - <position x="246" y="1292"/>
    - <connectionPointOut>
    - <relPosition x="190" y="15"/>
    - </connectionPointOut>
    - <expression>',"state",False))'</expression>
    - </inVariable>
    - <block localId="22" width="150" height="183" typeName="CONCAT">
    - <position x="493" y="1152"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="47"/>
    - <connection refLocalId="20">
    - <position x="493" y="1199"/>
    - <position x="436" y="1199"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="101"/>
    - <connection refLocalId="19">
    - <position x="493" y="1253"/>
    - <position x="436" y="1253"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN3">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="150" y="47"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="23" height="30" width="130">
    - <position x="300" y="355"/>
    - <connectionPointOut>
    - <relPosition x="130" y="15"/>
    - </connectionPointOut>
    - <expression>'",toggle='</expression>
    - </inVariable>
    - <block localId="24" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonToggle">
    - <position x="289" y="412"/>
    - <inputVariables>
    - <variable formalParameter="VALUE">
    - <connectionPointIn>
    - <relPosition x="0" y="30"/>
    - <connection refLocalId="27">
    - <position x="289" y="442"/>
    - <position x="220" y="442"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="CODE">
    - <connectionPointOut>
    - <relPosition x="140" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="27" height="30" width="90">
    - <position x="130" y="427"/>
    - <connectionPointOut>
    - <relPosition x="90" y="15"/>
    - </connectionPointOut>
    - <expression>toggle</expression>
    - </inVariable>
    - </FBD>
    - </body>
    - </pou>
    - <pou name="Led" pouType="functionBlock">
    - <interface>
    - <localVars>
    - <variable name="ID">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </localVars>
    - <inputVars>
    - <variable name="back_id">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="sele_id">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="state_in">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - </inputVars>
    - <localVars>
    - <variable name="init_Command">
    - <type>
    - <derived name="python_eval"/>
    - </type>
    - </variable>
    - <variable name="setstate_Command">
    - <type>
    - <derived name="python_poll"/>
    - </type>
    - </variable>
    - <variable name="GetLedState">
    - <type>
    - <derived name="GetBoolString"/>
    - </type>
    - </variable>
    - </localVars>
    - </interface>
    - <body>
    - <FBD>
    - <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
    - <position x="810" y="30"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <relPosition x="0" y="50"/>
    - <connection refLocalId="10">
    - <position x="810" y="80"/>
    - <position x="753" y="80"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="2" formalParameter="OUT">
    - <position x="810" y="140"/>
    - <position x="640" y="140"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="50"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="110"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <block localId="2" width="150" height="322" typeName="CONCAT">
    - <position x="490" y="90"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="50"/>
    - <connection refLocalId="3">
    - <position x="490" y="140"/>
    - <position x="415" y="140"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="11">
    - <position x="490" y="200"/>
    - <position x="415" y="200"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN3">
    - <connectionPointIn>
    - <relPosition x="0" y="170"/>
    - <connection refLocalId="5">
    - <position x="490" y="260"/>
    - <position x="415" y="260"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN4">
    - <connectionPointIn>
    - <relPosition x="0" y="230"/>
    - <connection refLocalId="12">
    - <position x="490" y="320"/>
    - <position x="414" y="320"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN5">
    - <connectionPointIn>
    - <relPosition x="0" y="290"/>
    - <connection refLocalId="9">
    - <position x="490" y="380"/>
    - <position x="414" y="380"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="150" y="50"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="3" height="30" width="400">
    - <position x="15" y="125"/>
    - <connectionPointOut>
    - <relPosition x="400" y="15"/>
    - </connectionPointOut>
    - <expression>'createSVGUIControl("button",back_id="'</expression>
    - </inVariable>
    - <block localId="4" width="125" height="140" typeName="python_poll" instanceName="setstate_Command">
    - <position x="782" y="536"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="110"/>
    - <connection refLocalId="7" formalParameter="OUT">
    - <position x="782" y="646"/>
    - <position x="615" y="646"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="50"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="110"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="5" height="30" width="140">
    - <position x="275" y="245"/>
    - <connectionPointOut>
    - <relPosition x="140" y="15"/>
    - </connectionPointOut>
    - <expression>'",sele_id="'</expression>
    - </inVariable>
    - <continuation name="CREATED" localId="6" height="30" width="110">
    - <position x="492" y="537"/>
    - <connectionPointOut>
    - <relPosition x="110" y="15"/>
    - </connectionPointOut>
    - </continuation>
    - <block localId="7" width="150" height="319" typeName="CONCAT">
    - <position x="465" y="597"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="49"/>
    - <connection refLocalId="14">
    - <position x="465" y="646"/>
    - <position x="351" y="646"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN3">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN4">
    - <connectionPointIn>
    - <relPosition x="0" y="226"/>
    - <connection refLocalId="28" formalParameter="CODE">
    - <position x="465" y="823"/>
    - <position x="351" y="823"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN5">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="150" y="49"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="8" height="30" width="53">
    - <position x="298" y="684"/>
    - <connectionPointOut>
    - <relPosition x="53" y="15"/>
    - </connectionPointOut>
    - <expression>ID</expression>
    - </inVariable>
    - <inVariable localId="9" height="30" width="300">
    - <position x="124" y="365"/>
    - <connectionPointOut>
    - <relPosition x="300" y="15"/>
    - </connectionPointOut>
    - <expression>'",toggle=True,active=False)'</expression>
    - </inVariable>
    - <inVariable localId="10" height="30" width="70">
    - <position x="683" y="65"/>
    - <connectionPointOut>
    - <relPosition x="70" y="15"/>
    - </connectionPointOut>
    - <expression>BOOL#1</expression>
    - </inVariable>
    - <inVariable localId="11" height="35" width="85">
    - <position x="330" y="185"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>back_id</expression>
    - </inVariable>
    - <inVariable localId="12" height="35" width="85">
    - <position x="329" y="305"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>sele_id</expression>
    - </inVariable>
    - <inVariable localId="14" height="30" width="120">
    - <position x="231" y="631"/>
    - <connectionPointOut>
    - <relPosition x="120" y="15"/>
    - </connectionPointOut>
    - <expression>'setAttr('</expression>
    - </inVariable>
    - <inVariable localId="15" height="30" width="122">
    - <position x="229" y="736"/>
    - <connectionPointOut>
    - <relPosition x="122" y="15"/>
    - </connectionPointOut>
    - <expression>',"state",'</expression>
    - </inVariable>
    - <inVariable localId="16" height="30" width="41">
    - <position x="310" y="868"/>
    - <connectionPointOut>
    - <relPosition x="41" y="15"/>
    - </connectionPointOut>
    - <expression>')'</expression>
    - </inVariable>
    - <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetLedState">
    - <position x="211" y="793"/>
    - <inputVariables>
    - <variable formalParameter="VALUE">
    - <connectionPointIn>
    - <relPosition x="0" y="30"/>
    - <connection refLocalId="32">
    - <position x="211" y="823"/>
    - <position x="153" y="823"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="CODE">
    - <connectionPointOut>
    - <relPosition x="140" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <outVariable localId="29" height="30" width="53">
    - <position x="987" y="125"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="1" formalParameter="RESULT">
    - <position x="987" y="140"/>
    - <position x="935" y="140"/>
    - </connection>
    - </connectionPointIn>
    - <expression>ID</expression>
    - </outVariable>
    - <connector name="CREATED" localId="30" height="30" width="110">
    - <position x="986" y="65"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="1" formalParameter="ACK">
    - <position x="986" y="80"/>
    - <position x="935" y="80"/>
    - </connection>
    - </connectionPointIn>
    - </connector>
    - <inVariable localId="32" height="30" width="90">
    - <position x="63" y="808"/>
    - <connectionPointOut>
    - <relPosition x="90" y="15"/>
    - </connectionPointOut>
    - <expression>state_in</expression>
    - </inVariable>
    - </FBD>
    - </body>
    - </pou>
    - </pous>
    - </types>
    - <instances>
    - <configurations/>
    - </instances>
    -</project>
    --- 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 @@
    -from pyjs import *
    -
    --- 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 @@
    -#!/usr/bin/env python
    -
    -import sys
    -import os
    -import shutil
    -from copy import copy
    -from os.path import join, dirname, basename, abspath, split, isfile, isdir
    -from optparse import OptionParser
    -import pyjs
    -from cStringIO import StringIO
    -try:
    - # Python 2.5 and above
    - from hashlib import md5
    -except:
    - import md5
    -import re
    -
    -usage = """
    - usage: %prog [options] <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
    -# -------------+-----------------------+----------------------+----------------------
    -# IE6 | ie6 | IE6 | ie6
    -# Opera | opera | Opera | opera
    -# Safari | safari | Safari | safari
    -# -- | gecko1_8 | Mozilla | mozilla
    -# -- | gecko | OldMoz | oldmoz
    -# Standard | all | (default code) | all
    -# Mozilla | gecko1_8, gecko | -- | --
    -# Old | safari, gecko, opera | -- | --
    -
    -version = "%prog pyjamas version 2006-08-19"
    -
    -# these names in lowercase need match the strings
    -# returned by "provider$user.agent" in order to be selected corretly
    -app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla']
    -
    -# usually defaults to e.g. /usr/share/pyjamas
    -_data_dir = os.path.join(pyjs.prefix, "share/pyjamas")
    -
    -
    -# .cache.html files produces look like this
    -CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$')
    -
    -# ok these are the three "default" library directories, containing
    -# the builtins (str, List, Dict, ord, round, len, range etc.)
    -# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.)
    -# and the contributed addons
    -
    -for p in ["library/builtins",
    - "library",
    - "addons"]:
    - p = os.path.join(_data_dir, p)
    - if os.path.isdir(p):
    - pyjs.path.append(p)
    -
    -
    -def read_boilerplate(data_dir, filename):
    - return open(join(data_dir, "builder/boilerplate", filename)).read()
    -
    -def copy_boilerplate(data_dir, filename, output_dir):
    - filename = join(data_dir, "builder/boilerplate", filename)
    - shutil.copy(filename, output_dir)
    -
    -
    -# taken and modified from python2.4
    -def copytree_exists(src, dst, symlinks=False):
    - if not os.path.exists(src):
    - return
    -
    - names = os.listdir(src)
    - try:
    - os.mkdir(dst)
    - except:
    - pass
    -
    - errors = []
    - for name in names:
    - if name.startswith('CVS'):
    - continue
    - if name.startswith('.git'):
    - continue
    - if name.startswith('.svn'):
    - continue
    -
    - srcname = os.path.join(src, name)
    - dstname = os.path.join(dst, name)
    - try:
    - if symlinks and os.path.islink(srcname):
    - linkto = os.readlink(srcname)
    - os.symlink(linkto, dstname)
    - elif isdir(srcname):
    - copytree_exists(srcname, dstname, symlinks)
    - else:
    - shutil.copy2(srcname, dstname)
    - except (IOError, os.error), why:
    - errors.append((srcname, dstname, why))
    - if errors:
    - print errors
    -
    -def check_html_file(source_file, dest_path):
    - """ Checks if a base HTML-file is available in the PyJamas
    - output directory.
    - If the HTML-file isn't available, it will be created.
    -
    - If a CSS-file with the same name is available
    - in the output directory, a reference to this CSS-file
    - is included.
    -
    - If no CSS-file is found, this function will look for a special
    - CSS-file in the output directory, with the name
    - "pyjamas_default.css", and if found it will be referenced
    - in the generated HTML-file.
    -
    - [thank you to stef mientki for contributing this function]
    - """
    -
    - base_html = """\
    -<html>
    - <!-- auto-generated html - you should consider editing and
    - adapting this to suit your requirements
    - -->
    - <head>
    - <meta name="pygwt:module" content="%(modulename)s">
    - %(css)s
    - <title>%(title)s</title>
    - </head>
    - <body bgcolor="white">
    - <script language="javascript" src="pygwt.js"></script>
    - </body>
    -</html>
    -"""
    -
    - filename = os.path.split ( source_file )[1]
    - mod_name = os.path.splitext ( filename )[0]
    - file_name = os.path.join ( dest_path, mod_name + '.html' )
    -
    - # if html file in output directory exists, leave it alone.
    - if os.path.exists ( file_name ):
    - return 0
    -
    - if os.path.exists (
    - os.path.join ( dest_path, mod_name + '.css' ) ) :
    - css = "<link rel='stylesheet' href='" + mod_name + ".css'>"
    - elif os.path.exists (
    - os.path.join ( dest_path, 'pyjamas_default.css' ) ) :
    - css = "<link rel='stylesheet' href='pyjamas_default.css'>"
    -
    - else:
    - css = ''
    -
    - title = 'PyJamas Auto-Generated HTML file ' + mod_name
    -
    - base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css}
    -
    - fh = open (file_name, 'w')
    - fh.write (base_html)
    - fh.close ()
    -
    - return 1
    -
    -
    -def build(app_name, output, js_includes=(), debug=False, dynamic=0,
    - data_dir=None, cache_buster=False, optimize=False):
    -
    - # make sure the output directory is always created in the current working
    - # directory or at the place given if it is an absolute path.
    - output = os.path.abspath(output)
    - msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals()
    - if debug:
    - msg += " with debugging statements"
    - print msg
    -
    - # check the output directory
    - if os.path.exists(output) and not os.path.isdir(output):
    - print >>sys.stderr, "Output destination %s exists and is not a directory" % output
    - return
    - if not os.path.isdir(output):
    - try:
    - print "Creating output directory"
    - os.mkdir(output)
    - except StandardError, e:
    - print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e)
    -
    - ## public dir
    - for p in pyjs.path:
    - pub_dir = join(p, 'public')
    - if isdir(pub_dir):
    - print "Copying: public directory of library %r" % p
    - copytree_exists(pub_dir, output)
    -
    - ## AppName.html - can be in current or public directory
    - html_input_filename = app_name + ".html"
    - html_output_filename = join(output, basename(html_input_filename))
    - if os.path.isfile(html_input_filename):
    - if not os.path.isfile(html_output_filename) or \
    - os.path.getmtime(html_input_filename) > \
    - os.path.getmtime(html_output_filename):
    - try:
    - shutil.copy(html_input_filename, html_output_filename)
    - except:
    - print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename
    -
    - print "Copying: %(html_input_filename)s" % locals()
    -
    - if check_html_file(html_input_filename, output):
    - print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename
    -
    - ## pygwt.js
    -
    - print "Copying: pygwt.js"
    -
    - pygwt_js_template = read_boilerplate(data_dir, "pygwt.js")
    - pygwt_js_output = open(join(output, "pygwt.js"), "w")
    -
    - print >>pygwt_js_output, pygwt_js_template
    -
    - pygwt_js_output.close()
    -
    - ## Images
    -
    - print "Copying: Images and History"
    - copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_topleft.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_topright.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output)
    - copy_boilerplate(data_dir, "corner_dialog_edge.png", output)
    - copy_boilerplate(data_dir, "tree_closed.gif", output)
    - copy_boilerplate(data_dir, "tree_open.gif", output)
    - copy_boilerplate(data_dir, "tree_white.gif", output)
    - copy_boilerplate(data_dir, "history.html", output)
    -
    -
    - ## all.cache.html
    - app_files = generateAppFiles(data_dir, js_includes, app_name, debug,
    - output, dynamic, cache_buster, optimize)
    -
    - ## AppName.nocache.html
    -
    - print "Creating: %(app_name)s.nocache.html" % locals()
    -
    - home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html")
    - home_nocache_html_output = open(join(output, app_name + ".nocache.html"),
    - "w")
    -
    - # the selector templ is added to the selectScript function
    - select_tmpl = """O(["true","%s"],"%s");"""
    - script_selectors = StringIO()
    -
    - for platform, file_prefix in app_files:
    - print >> script_selectors, select_tmpl % (platform, file_prefix)
    -
    - print >>home_nocache_html_output, home_nocache_html_template % dict(
    - app_name = app_name,
    - script_selectors = script_selectors.getvalue(),
    - )
    -
    - home_nocache_html_output.close()
    -
    - print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals()
    -
    -
    -def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic,
    - cache_buster, optimize):
    -
    - all_cache_html_template = read_boilerplate(data_dir, "all.cache.html")
    - mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html")
    -
    - # clean out the old ones first
    - for name in os.listdir(output):
    - if CACHE_HTML_PAT.match(name):
    - p = join(output, name)
    - print "Deleting existing app file %s" % p
    - os.unlink(p)
    -
    - app_files = []
    - tmpl = read_boilerplate(data_dir, "all.cache.html")
    - parser = pyjs.PlatformParser("platform")
    - app_headers = ''
    - scripts = ['<script type="text/javascript" src="%s"></script>'%script \
    - for script in js_includes]
    - app_body = '\n'.join(scripts)
    -
    - mod_code = {}
    - mod_libs = {}
    - modules = {}
    - app_libs = {}
    - early_app_libs = {}
    - app_code = {}
    - overrides = {}
    - pover = {}
    - app_modnames = {}
    - mod_levels = {}
    -
    - # First, generate all the code.
    - # Second, (dynamic only), post-analyse the places where modules
    - # haven't changed
    - # Third, write everything out.
    -
    - for platform in app_platforms:
    -
    - mod_code[platform] = {}
    - mod_libs[platform] = {}
    - modules[platform] = []
    - pover[platform] = {}
    - app_libs[platform] = ''
    - early_app_libs[platform] = ''
    - app_code[platform] = {}
    - app_modnames[platform] = {}
    -
    - # Application.Platform.cache.html
    -
    - parser.setPlatform(platform)
    - app_translator = pyjs.AppTranslator(
    - parser=parser, dynamic=dynamic, optimize=optimize)
    - early_app_libs[platform], appcode = \
    - app_translator.translate(None, is_app=False,
    - debug=debug,
    - library_modules=['dynamicajax.js',
    - '_pyjs.js', 'sys',
    - 'pyjslib'])
    - pover[platform].update(app_translator.overrides.items())
    - for mname, name in app_translator.overrides.items():
    - pd = overrides.setdefault(mname, {})
    - pd[platform] = name
    -
    - print appcode
    - #mod_code[platform][app_name] = appcode
    -
    - # platform.Module.cache.js
    -
    - modules_done = ['pyjslib', 'sys', '_pyjs.js']
    - #modules_to_do = [app_name] + app_translator.library_modules
    - modules_to_do = [app_name] + app_translator.library_modules
    -
    - dependencies = {}
    -
    - deps = map(pyjs.strip_py, modules_to_do)
    - for d in deps:
    - sublist = add_subdeps(dependencies, d)
    - modules_to_do += sublist
    - deps = uniquify(deps)
    - #dependencies[app_name] = deps
    -
    - modules[platform] = modules_done + modules_to_do
    -
    - while modules_to_do:
    -
    - #print "modules to do", modules_to_do
    -
    - mn = modules_to_do.pop()
    - mod_name = pyjs.strip_py(mn)
    -
    - if mod_name in modules_done:
    - continue
    -
    - modules_done.append(mod_name)
    -
    - mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name)
    -
    - parser.setPlatform(platform)
    - mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize)
    - mod_libs[platform][mod_name], mod_code[platform][mod_name] = \
    - mod_translator.translate(mod_name,
    - is_app=False,
    - debug=debug)
    - pover[platform].update(mod_translator.overrides.items())
    - for mname, name in mod_translator.overrides.items():
    - pd = overrides.setdefault(mname, {})
    - pd[platform] = name
    -
    - mods = mod_translator.library_modules
    - modules_to_do += mods
    - modules[platform] += mods
    -
    - deps = map(pyjs.strip_py, mods)
    - sd = subdeps(mod_name)
    - if len(sd) > 1:
    - deps += sd[:-1]
    - while mod_name in deps:
    - deps.remove(mod_name)
    -
    - #print
    - #print
    - #print "modname preadd:", mod_name, deps
    - #print
    - #print
    - for d in deps:
    - sublist = add_subdeps(dependencies, d)
    - modules_to_do += sublist
    - modules_to_do += add_subdeps(dependencies, mod_name)
    - #print "modname:", mod_name, deps
    - deps = uniquify(deps)
    - #print "modname:", mod_name, deps
    - dependencies[mod_name] = deps
    -
    - # work out the dependency ordering of the modules
    -
    - mod_levels[platform] = make_deps(None, dependencies, modules_done)
    -
    - # now write everything out
    -
    - for platform in app_platforms:
    -
    - early_app_libs_ = early_app_libs[platform]
    - app_libs_ = app_libs[platform]
    - app_code_ = app_code[platform]
    - #modules_ = filter_mods(app_name, modules[platform])
    - mods = flattenlist(mod_levels[platform])
    - mods.reverse()
    - modules_ = filter_mods(None, mods)
    -
    - for mod_name in modules_:
    -
    - mod_code_ = mod_code[platform][mod_name]
    -
    - mod_name = pyjs.strip_py(mod_name)
    -
    - override_name = "%s.%s" % (platform.lower(), mod_name)
    - if pover[platform].has_key(override_name):
    - mod_cache_name = "%s.cache.js" % (override_name)
    - else:
    - mod_cache_name = "%s.cache.js" % (mod_name)
    -
    - print "Creating: " + mod_cache_name
    -
    - modlevels = make_deps(None, dependencies, dependencies[mod_name])
    -
    - modnames = []
    -
    - for md in modlevels:
    - mnames = map(lambda x: "'%s'" % x, md)
    - mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
    - modnames.append(mnames)
    -
    - modnames.reverse()
    - modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames)
    -
    - # convert the overrides
    -
    - overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
    - overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
    -
    - if dynamic:
    - mod_cache_html_output = open(join(output, mod_cache_name), "w")
    - else:
    - mod_cache_html_output = StringIO()
    -
    - print >>mod_cache_html_output, mod_cache_html_template % dict(
    - mod_name = mod_name,
    - app_name = app_name,
    - modnames = modnames,
    - overrides = overnames,
    - mod_libs = mod_libs[platform][mod_name],
    - dynamic = dynamic,
    - mod_code = mod_code_,
    - )
    -
    - if dynamic:
    - mod_cache_html_output.close()
    - else:
    - mod_cache_html_output.seek(0)
    - app_libs_ += mod_cache_html_output.read()
    -
    - # write out the dependency ordering of the modules
    -
    - app_modnames = []
    -
    - for md in mod_levels[platform]:
    - mnames = map(lambda x: "'%s'" % x, md)
    - mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
    - app_modnames.append(mnames)
    -
    - app_modnames.reverse()
    - app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames)
    -
    - # convert the overrides
    -
    - overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
    - overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
    -
    - #print "platform names", platform, overnames
    - #print pover
    -
    - # now write app.allcache including dependency-ordered list of
    - # library modules
    -
    - file_contents = all_cache_html_template % dict(
    - app_name = app_name,
    - early_app_libs = early_app_libs_,
    - app_libs = app_libs_,
    - app_code = app_code_,
    - app_body = app_body,
    - overrides = overnames,
    - platform = platform.lower(),
    - dynamic = dynamic,
    - app_modnames = app_modnames,
    - app_headers = app_headers
    - )
    - if cache_buster:
    - digest = md5.new(file_contents).hexdigest()
    - file_name = "%s.%s.%s" % (platform.lower(), app_name, digest)
    - else:
    - file_name = "%s.%s" % (platform.lower(), app_name)
    - file_name += ".cache.html"
    - out_path = join(output, file_name)
    - out_file = open(out_path, 'w')
    - out_file.write(file_contents)
    - out_file.close()
    - app_files.append((platform.lower(), file_name))
    - print "Created app file %s:%s: %s" % (
    - app_name, platform, out_path)
    -
    - return app_files
    -
    -def flattenlist(ll):
    - res = []
    - for l in ll:
    - res += l
    - return res
    -
    -# creates sub-dependencies e.g. pyjamas.ui.Widget
    -# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
    -def subdeps(m):
    - d = []
    - m = m.split(".")
    - for i in range(0, len(m)):
    - d.append('.'.join(m[:i+1]))
    - return d
    -
    -import time
    -
    -def add_subdeps(deps, mod_name):
    - sd = subdeps(mod_name)
    - if len(sd) == 1:
    - return []
    - #print "subdeps", mod_name, sd
    - #print "deps", deps
    - res = []
    - for i in range(0, len(sd)-1):
    - parent = sd[i]
    - child = sd[i+1]
    - l = deps.get(child, [])
    - l.append(parent)
    - deps[child] = l
    - if parent not in res:
    - res.append(parent)
    - #print deps
    - return res
    -
    -# makes unique and preserves list order
    -def uniquify(md):
    - res = []
    - for m in md:
    - if m not in res:
    - res.append(m)
    - return res
    -
    -def filter_mods(app_name, md):
    - while 'sys' in md:
    - md.remove('sys')
    - while 'pyjslib' in md:
    - md.remove('pyjslib')
    - while app_name in md:
    - md.remove(app_name)
    - md = filter(lambda x: not x.endswith('.js'), md)
    - md = map(pyjs.strip_py, md)
    -
    - return uniquify(md)
    -
    -def filter_deps(app_name, deps):
    -
    - res = {}
    - for (k, l) in deps.items():
    - mods = filter_mods(k, l)
    - while k in mods:
    - mods.remove(k)
    - res[k] = mods
    - return res
    -
    -def has_nodeps(mod, deps):
    - if not deps.has_key(mod) or not deps[mod]:
    - return True
    - return False
    -
    -def nodeps_list(mod_list, deps):
    - res = []
    - for mod in mod_list:
    - if has_nodeps(mod, deps):
    - res.append(mod)
    - return res
    -
    -# this function takes a dictionary of dependent modules and
    -# creates a list of lists. the first list will be modules
    -# that have no dependencies; the second list will be those
    -# modules that have the first list as dependencies; the
    -# third will be those modules that have the first and second...
    -# etc.
    -
    -
    -def make_deps(app_name, deps, mod_list):
    - print "Calculating Dependencies ..."
    - mod_list = filter_mods(app_name, mod_list)
    - deps = filter_deps(app_name, deps)
    -
    - if not mod_list:
    - return []
    -
    - #print mod_list
    - #print deps
    -
    - ordered_deps = []
    - last_len = -1
    - while deps:
    - l_deps = len(deps)
    - #print l_deps
    - if l_deps==last_len:
    - for m, dl in deps.items():
    - for d in dl:
    - if m in deps.get(d, []):
    - raise Exception('Circular Imports found: \n%s %s -> %s %s'
    - % (m, dl, d, deps[d]))
    - #raise Exception('Could not calculate dependencies: \n%s' % deps)
    - break
    - last_len = l_deps
    - #print "modlist", mod_list
    - nodeps = nodeps_list(mod_list, deps)
    - #print "nodeps", nodeps
    - mod_list = filter(lambda x: x not in nodeps, mod_list)
    - newdeps = {}
    - for k in deps.keys():
    - depslist = deps[k]
    - depslist = filter(lambda x: x not in nodeps, depslist)
    - if depslist:
    - newdeps[k] = depslist
    - #print "newdeps", newdeps
    - deps = newdeps
    - ordered_deps.append(nodeps)
    - #time.sleep(0)
    -
    - if mod_list:
    - ordered_deps.append(mod_list) # last dependencies - usually the app(s)
    -
    - ordered_deps.reverse()
    -
    - return ordered_deps
    -
    -def main():
    - global app_platforms
    -
    - parser = OptionParser(usage = usage, version = version)
    - parser.add_option("-o", "--output", dest="output",
    - help="directory to which the webapp should be written")
    - parser.add_option("-j", "--include-js", dest="js_includes", action="append",
    - help="javascripts to load into the same frame as the rest of the script")
    - parser.add_option("-I", "--library_dir", dest="library_dirs",
    - action="append", help="additional paths appended to PYJSPATH")
    - parser.add_option("-D", "--data_dir", dest="data_dir",
    - help="path for data directory")
    - parser.add_option("-m", "--dynamic-modules", action="store_true",
    - dest="dynamic", default=False,
    - help="Split output into separate dynamically-loaded modules (experimental)")
    - parser.add_option("-P", "--platforms", dest="platforms",
    - help="platforms to build for, comma-separated")
    - parser.add_option("-d", "--debug", action="store_true", dest="debug")
    - parser.add_option("-O", "--optimize", action="store_true",
    - dest="optimize", default=False,
    - help="Optimize generated code (removes all print statements)",
    - )
    - parser.add_option("-c", "--cache_buster", action="store_true",
    - dest="cache_buster",
    - help="Enable browser cache-busting (MD5 hash added to output filenames)")
    -
    - parser.set_defaults(output = "output", js_includes=[], library_dirs=[],
    - platforms=(','.join(app_platforms)),
    - data_dir=os.path.join(sys.prefix, "share/pyjamas"),
    - dynamic=False,
    - cache_buster=False,
    - debug=False)
    - (options, args) = parser.parse_args()
    - if len(args) != 1:
    - parser.error("incorrect number of arguments")
    -
    - data_dir = abspath(options.data_dir)
    -
    - app_path = args[0]
    - if app_path.endswith('.py'):
    - app_path = abspath(app_path)
    - if not isfile(app_path):
    - parser.error("Application file not found %r" % app_path)
    - app_path, app_name = split(app_path)
    - app_name = app_name[:-3]
    - pyjs.path.append(app_path)
    - elif os.path.sep in app_path:
    - parser.error("Not a valid module declaration %r" % app_path)
    - else:
    - app_name = app_path
    -
    - for d in options.library_dirs:
    - pyjs.path.append(abspath(d))
    -
    - if options.platforms:
    - app_platforms = options.platforms.split(',')
    -
    - # this is mostly for getting boilerplate stuff
    - data_dir = os.path.abspath(options.data_dir)
    -
    - build(app_name, options.output, options.js_includes,
    - options.debug, options.dynamic and 1 or 0, data_dir,
    - options.cache_buster, options.optimize)
    -
    -if __name__ == "__main__":
    - main()
    -
    --- 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 @@
    -# jsonrpc.py
    -# original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas
    -# also from: http://www.pimentech.fr/technologies/outils
    -from django.utils import simplejson
    -from django.http import HttpResponse
    -import sys
    -
    -from pyjs.jsonrpc import JSONRPCServiceBase
    -# JSONRPCService and jsonremote are used in combination to drastically
    -# simplify the provision of JSONRPC services. use as follows:
    -#
    -# jsonservice = JSONRPCService()
    -#
    -# @jsonremote(jsonservice)
    -# def test(request, echo_param):
    -# return "echoing the param back: %s" % echo_param
    -#
    -# dump jsonservice into urlpatterns:
    -# (r'^service1/$', 'djangoapp.views.jsonservice'),
    -
    -class JSONRPCService(JSONRPCServiceBase):
    -
    - def __call__(self, request, extra=None):
    - return self.process(request.raw_post_data)
    -
    -def jsonremote(service):
    - """Make JSONRPCService a decorator so that you can write :
    -
    - from jsonrpc import JSONRPCService
    - chatservice = JSONRPCService()
    -
    - @jsonremote(chatservice)
    - def login(request, user_name):
    - (...)
    - """
    - def remotify(func):
    - if isinstance(service, JSONRPCService):
    - service.add_method(func.__name__, func)
    - else:
    - emsg = 'Service "%s" not found' % str(service.__name__)
    - raise NotImplementedError, emsg
    - return func
    - return remotify
    -
    -
    -# FormProcessor provides a mechanism for turning Django Forms into JSONRPC
    -# Services. If you have an existing Django app which makes prevalent
    -# use of Django Forms it will save you rewriting the app.
    -# use as follows. in djangoapp/views.py :
    -#
    -# class SimpleForm(forms.Form):
    -# testfield = forms.CharField(max_length=100)
    -#
    -# class SimpleForm2(forms.Form):
    -# testfield = forms.CharField(max_length=20)
    -#
    -# processor = FormProcessor({'processsimpleform': SimpleForm,
    -# 'processsimpleform2': SimpleForm2})
    -#
    -# this will result in a JSONRPC service being created with two
    -# RPC functions. dump "processor" into urlpatterns to make it
    -# part of the app:
    -# (r'^formsservice/$', 'djangoapp.views.processor'),
    -
    -from django import forms
    -
    -def builderrors(form):
    - d = {}
    - for error in form.errors.keys():
    - if error not in d:
    - d[error] = []
    - for errorval in form.errors[error]:
    - d[error].append(unicode(errorval))
    - return d
    -
    -
    -# contains the list of arguments in each field
    -field_names = {
    - 'CharField': ['max_length', 'min_length'],
    - 'IntegerField': ['max_value', 'min_value'],
    - 'FloatField': ['max_value', 'min_value'],
    - 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'],
    - 'DateField': ['input_formats'],
    - 'DateTimeField': ['input_formats'],
    - 'TimeField': ['input_formats'],
    - 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr
    - 'EmailField': ['max_length', 'min_length'],
    - 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'],
    - 'ChoiceField': ['choices'],
    - 'FilePathField': ['path', 'match', 'recursive', 'choices'],
    - 'IPAddressField': ['max_length', 'min_length'],
    - }
    -
    -def describe_field_errors(field):
    - res = {}
    - field_type = field.__class__.__name__
    - msgs = {}
    - for n, m in field.error_messages.items():
    - msgs[n] = unicode(m)
    - res['error_messages'] = msgs
    - if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
    - res['fields'] = map(describe_field, field.fields)
    - return res
    -
    -def describe_fields_errors(fields, field_names):
    - res = {}
    - if not field_names:
    - field_names = fields.keys()
    - for name in field_names:
    - field = fields[name]
    - res[name] = describe_field_errors(field)
    - return res
    -
    -def describe_field(field):
    - res = {}
    - field_type = field.__class__.__name__
    - for fname in field_names.get(field_type, []) + \
    - ['help_text', 'label', 'initial', 'required']:
    - res[fname] = getattr(field, fname)
    - if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
    - res['fields'] = map(describe_field, field.fields)
    - return res
    -
    -def describe_fields(fields, field_names):
    - res = {}
    - if not field_names:
    - field_names = fields.keys()
    - for name in field_names:
    - field = fields[name]
    - res[name] = describe_field(field)
    - return res
    -
    -class FormProcessor(JSONRPCService):
    - def __init__(self, forms, _formcls=None):
    -
    - if _formcls is None:
    - JSONRPCService.__init__(self)
    - for k in forms.keys():
    - s = FormProcessor({}, forms[k])
    - self.add_method(k, s.__process)
    - else:
    - JSONRPCService.__init__(self, forms)
    - self.formcls = _formcls
    -
    - def __process(self, request, params, command=None):
    -
    - f = self.formcls(params)
    -
    - if command is None: # just validate
    - if not f.is_valid():
    - return {'success':False, 'errors': builderrors(f)}
    - return {'success':True}
    -
    - elif command.has_key('describe_errors'):
    - field_names = command['describe_errors']
    - return describe_fields_errors(f.fields, field_names)
    -
    - elif command.has_key('describe'):
    - field_names = command['describe']
    - return describe_fields(f.fields, field_names)
    -
    - elif command.has_key('save'):
    - if not f.is_valid():
    - return {'success':False, 'errors': builderrors(f)}
    - instance = f.save() # XXX: if you want more, over-ride save.
    - return {'success': True, 'instance': json_convert(instance) }
    -
    - elif command.has_key('html'):
    - return {'success': True, 'html': f.as_table()}
    -
    - return "unrecognised command"
    -
    -
    -
    -
    -# The following is incredibly convenient for saving vast amounts of
    -# coding, avoiding doing silly things like this:
    -# jsonresult = {'field1': djangoobject.field1,
    -# 'field2': djangoobject.date.strftime('%Y.%M'),
    -# ..... }
    -#
    -# The date/time flatten function is there because JSONRPC doesn't
    -# support date/time objects or formats, so conversion to a string
    -# is the most logical choice. pyjamas, being python, can easily
    -# be used to parse the string result at the other end.
    -#
    -# use as follows:
    -#
    -# jsonservice = JSONRPCService()
    -#
    -# @jsonremote(jsonservice)
    -# def list_some_model(request, start=0, count=10):
    -# l = SomeDjangoModelClass.objects.filter()
    -# res = json_convert(l[start:end])
    -#
    -# @jsonremote(jsonservice)
    -# def list_another_model(request, start=0, count=10):
    -# l = AnotherDjangoModelClass.objects.filter()
    -# res = json_convert(l[start:end])
    -#
    -# dump jsonservice into urlpatterns to make the two RPC functions,
    -# list_some_model and list_another_model part of the django app:
    -# (r'^service1/$', 'djangoapp.views.jsonservice'),
    -
    -from django.core.serializers import serialize
    -import datetime
    -from datetime import date
    -
    -def dict_datetimeflatten(item):
    - d = {}
    - for k, v in item.items():
    - k = str(k)
    - if isinstance(v, datetime.date):
    - d[k] = str(v)
    - elif isinstance(v, dict):
    - d[k] = dict_datetimeflatten(v)
    - else:
    - d[k] = v
    - return d
    -
    -def json_convert(l, fields=None):
    - res = []
    - for item in serialize('python', l, fields=fields):
    - res.append(dict_datetimeflatten(item))
    - return res
    -
    --- 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
    -import types
    -import sys
    -
    -class JSONRPCServiceBase:
    -
    - def __init__(self):
    - self.methods={}
    -
    - def response(self, id, result):
    - return simplejson.dumps({'version': '1.1', 'id':id,
    - 'result':result, 'error':None})
    - def error(self, id, code, message):
    - return simplejson.dumps({'id': id,
    - 'version': '1.1',
    - 'error': {'name': 'JSONRPCError',
    - 'code': code,
    - 'message': message
    - }
    - })
    -
    - def add_method(self, name, method):
    - self.methods[name] = method
    -
    - def process(self, data):
    - data = simplejson.loads(data)
    - id, method, params = data["id"], data["method"], data["params"]
    - if method in self.methods:
    - try:
    - result =self.methods[method](*params)
    - return self.response(id, result)
    - except BaseException:
    - etype, eval, etb = sys.exc_info()
    - return self.error(id, 100, '%s: %s' %(etype.__name__, eval))
    - except:
    - etype, eval, etb = sys.exc_info()
    - return self.error(id, 100, 'Exception %s: %s' %(etype, eval))
    - else:
    - return self.error(id, 100, 'method "%s" does not exist' % method)
    -
    - def listmethods(self):
    - return self.methods.keys()
    -
    --- 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):
    -
    - def serve(self):
    - return self.process(request.body.read())
    -
    - def __call__(self,func):
    - self.methods[func.__name__]=func
    - return 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))
    - {
    - klass_object[i] = v;
    - }
    - }
    -
    - function klass_inherit() {}
    - klass_inherit.prototype = klass_object;
    - klass.prototype = new klass_inherit();
    - klass_object.constructor = klass;
    - klass.prototype.__class__ = klass_object;
    -
    - for (var i in base.prototype) {
    - v = base.prototype[i];
    - if (typeof v == "function" && v.instance_method)
    - {
    - klass.prototype[i] = v;
    - }
    - }
    -}
    -
    -/* creates a class, derived from bases, with methods and variables */
    -function pyjs_type(clsname, bases, methods)
    -{
    - var fn_cls = function() {};
    - fn_cls.__name__ = clsname;
    - var fn = function() {
    - var instance = new fn_cls();
    - if(instance.__init__) instance.__init__.apply(instance, arguments);
    - return instance;
    - }
    - fn_cls.__initialize__ = function() {
    - if (fn_cls.__was_initialized__) return;
    - fn_cls.__was_initialized__ = true;
    - fn_cls.__extend_baseclasses();
    - fn_cls.prototype.__class__.__new__ = fn;
    - fn_cls.prototype.__class__.__name__ = clsname;
    - }
    - fn_cls.__extend_baseclasses = function() {
    - var bi;
    - for (bi in fn_cls.__baseclasses)
    - {
    - var b = fn_cls.__baseclasses[bi];
    - if (b.__was_initialized__)
    - {
    - continue;
    - }
    - b.__initialize__();
    - }
    - for (bi in fn_cls.__baseclasses)
    - {
    - var b = fn_cls.__baseclasses[bi];
    - pyjs_extend(fn_cls, b);
    - }
    - }
    - if (!bases) {
    - bases = [pyjslib.__Object];
    - }
    - fn_cls.__baseclasses = bases;
    -
    - fn_cls.__initialize__();
    -
    - for (k in methods) {
    - var mth = methods[k];
    - var mtype = typeof mth;
    - if (mtype == "function" ) {
    - fn_cls.prototype[k] = mth;
    - fn_cls.prototype.__class__[k] = function () {
    - return fn_cls.prototype[k].call.apply(
    - fn_cls.prototype[k], arguments);
    - };
    - fn_cls.prototype.__class__[k].unbound_method = true;
    - fn_cls.prototype.instance_method = true;
    - fn_cls.prototype.__class__[k].__name__ = k;
    - fn_cls.prototype[k].__name__ = k;
    - } else {
    - fn_cls.prototype.__class__[k] = mth;
    - }
    - }
    - return fn;
    -}
    -function pyjs_kwargs_call(obj, func, star_args, args)
    -{
    - var call_args;
    -
    - if (star_args)
    - {
    - if (!pyjslib.isIteratable(star_args))
    - {
    - throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args)));
    - }
    - call_args = Array();
    - var __i = star_args.__iter__();
    - var i = 0;
    - try {
    - while (true) {
    - call_args[i]=__i.next();
    - i++;
    - }
    - } catch (e) {
    - if (e != pyjslib.StopIteration) {
    - throw e;
    - }
    - }
    -
    - if (args)
    - {
    - var n = star_args.length;
    - for (var i=0; i < args.length; i++) {
    - call_args[n+i]=args[i];
    - }
    - }
    - }
    - else
    - {
    - call_args = args;
    - }
    - return func.apply(obj, call_args);
    -}
    -
    -function pyjs_kwargs_function_call(func, star_args, args)
    -{
    - return pyjs_kwargs_call(null, func, star_args, args);
    -}
    -
    -function pyjs_kwargs_method_call(obj, method_name, star_args, args)
    -{
    - var method = obj[method_name];
    - if (method.parse_kwargs)
    - {
    - args = method.parse_kwargs.apply(null, args);
    - }
    - return pyjs_kwargs_call(obj, method, star_args, args);
    -}
    -
    -//String.prototype.__getitem__ = String.prototype.charAt;
    -//String.prototype.upper = String.prototype.toUpperCase;
    -//String.prototype.lower = String.prototype.toLowerCase;
    -//String.prototype.find=pyjslib.String_find;
    -//String.prototype.join=pyjslib.String_join;
    -//String.prototype.isdigit=pyjslib.String_isdigit;
    -//String.prototype.__iter__=pyjslib.String___iter__;
    -//
    -//String.prototype.__replace=String.prototype.replace;
    -//String.prototype.replace=pyjslib.String_replace;
    -//
    -//String.prototype.split=pyjslib.String_split;
    -//String.prototype.strip=pyjslib.String_strip;
    -//String.prototype.lstrip=pyjslib.String_lstrip;
    -//String.prototype.rstrip=pyjslib.String_rstrip;
    -//String.prototype.startswith=pyjslib.String_startswith;
    -
    -var str = String;
    -
    --- 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
    -// global variables.
    -
    - var at, // The index of the current character
    - ch, // The current character
    - escapee = {
    - '"': '"',
    - '\\': '\\',
    - '/': '/',
    - b: '\b',
    - f: '\f',
    - n: '\n',
    - r: '\r',
    - t: '\t'
    - },
    - text,
    -
    - error = function (m) {
    -
    -// Call error when something is wrong.
    -
    - throw {
    - name: 'SyntaxError',
    - message: m,
    - at: at,
    - text: text
    - };
    - },
    -
    - next = function (c) {
    -
    -// If a c parameter is provided, verify that it matches the current character.
    -
    - if (c && c !== ch) {
    - error("Expected '" + c + "' instead of '" + ch + "'");
    - }
    -
    -// Get the next character. When there are no more characters,
    -// return the empty string.
    -
    - ch = text.charAt(at);
    - at += 1;
    - return ch;
    - },
    -
    - number = function () {
    -
    -// Parse a number value.
    -
    - var number,
    - string = '';
    -
    - if (ch === '-') {
    - string = '-';
    - next('-');
    - }
    - while (ch >= '0' && ch <= '9') {
    - string += ch;
    - next();
    - }
    - if (ch === '.') {
    - string += '.';
    - while (next() && ch >= '0' && ch <= '9') {
    - string += ch;
    - }
    - }
    - if (ch === 'e' || ch === 'E') {
    - string += ch;
    - next();
    - if (ch === '-' || ch === '+') {
    - string += ch;
    - next();
    - }
    - while (ch >= '0' && ch <= '9') {
    - string += ch;
    - next();
    - }
    - }
    - number = +string;
    - if (isNaN(number)) {
    - error("Bad number");
    - } else {
    - return number;
    - }
    - },
    -
    - string = function () {
    -
    -// Parse a string value.
    -
    - var hex,
    - i,
    - string = '',
    - uffff;
    -
    -// When parsing for string values, we must look for " and \ characters.
    -
    - if (ch === '"') {
    - while (next()) {
    - if (ch === '"') {
    - next();
    - return string;
    - } else if (ch === '\\') {
    - next();
    - if (ch === 'u') {
    - uffff = 0;
    - for (i = 0; i < 4; i += 1) {
    - hex = parseInt(next(), 16);
    - if (!isFinite(hex)) {
    - break;
    - }
    - uffff = uffff * 16 + hex;
    - }
    - string += String.fromCharCode(uffff);
    - } else if (typeof escapee[ch] === 'string') {
    - string += escapee[ch];
    - } else {
    - break;
    - }
    - } else {
    - string += ch;
    - }
    - }
    - }
    - error("Bad string");
    - },
    -
    - white = function () {
    -
    -// Skip whitespace.
    -
    - while (ch && ch <= ' ') {
    - next();
    - }
    - },
    -
    - word = function () {
    -
    -// true, false, or null.
    -
    - switch (ch) {
    - case 't':
    - next('t');
    - next('r');
    - next('u');
    - next('e');
    - return true;
    - case 'f':
    - next('f');
    - next('a');
    - next('l');
    - next('s');
    - next('e');
    - return false;
    - case 'n':
    - next('n');
    - next('u');
    - next('l');
    - next('l');
    - return null;
    - }
    - error("Unexpected '" + ch + "'");
    - },
    -
    - value, // Place holder for the value function.
    -
    - array = function () {
    -
    -// Parse an array value.
    -
    - var array = [];
    -
    - if (ch === '[') {
    - next('[');
    - white();
    - if (ch === ']') {
    - next(']');
    - return array; // empty array
    - }
    - while (ch) {
    - array.push(value());
    - white();
    - if (ch === ']') {
    - next(']');
    - return array;
    - }
    - next(',');
    - white();
    - }
    - }
    - error("Bad array");
    - },
    -
    - object = function () {
    -
    -// Parse an object value.
    -
    - var key,
    - object = {};
    -
    - if (ch === '{') {
    - next('{');
    - white();
    - if (ch === '}') {
    - next('}');
    - return object; // empty object
    - }
    - while (ch) {
    - key = string();
    - white();
    - next(':');
    - if (Object.hasOwnProperty.call(object, key)) {
    - error('Duplicate key "' + key + '"');
    - }
    - object[key] = value();
    - white();
    - if (ch === '}') {
    - next('}');
    - return object;
    - }
    - next(',');
    - white();
    - }
    - }
    - error("Bad object");
    - };
    -
    - value = function () {
    -
    -// Parse a JSON value. It could be an object, an array, a string, a number,
    -// or a word.
    -
    - white();
    - switch (ch) {
    - case '{':
    - return object();
    - case '[':
    - return array();
    - case '"':
    - return string();
    - case '-':
    - return number();
    - default:
    - return ch >= '0' && ch <= '9' ? number() : word();
    - }
    - };
    -
    -// Return the json_parse function. It will have access to all of the above
    -// functions and variables.
    -
    - return function (source, reviver) {
    - var result;
    -
    - text = source;
    - at = 0;
    - ch = ' ';
    - result = value();
    - white();
    - if (ch) {
    - error("Syntax error");
    - }
    -
    -// If there is a reviver function, we recursively walk the new structure,
    -// passing each name/value pair to the reviver function for possible
    -// transformation, starting with a temporary root object that holds the result
    -// in an empty key. If there is not a reviver function, we simply return the
    -// result.
    -
    - return typeof reviver === 'function' ? (function walk(holder, key) {
    - var k, v, value = holder[key];
    - if (value && typeof value === 'object') {
    - for (k in value) {
    - if (Object.hasOwnProperty.call(value, k)) {
    - v = walk(value, k);
    - if (v !== undefined) {
    - value[k] = v;
    - } else {
    - delete value[k];
    - }
    - }
    - }
    - }
    - return reviver.call(holder, key, value);
    - }({'': result}, '')) : result;
    - };
    -}());
    --- 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):
    - """
    - """
    -
    - JS("""
    - var cache_file;
    -
    - if (module_name == "sys" || module_name == 'pyjslib')
    - {
    - /*module_load_request[module_name] = 1;*/
    - return;
    - }
    -
    - if (path == null)
    - {
    - path = './';
    - }
    -
    - var override_name = sys.platform + "." + module_name;
    - if (((sys.overrides != null) &&
    - (sys.overrides.has_key(override_name))))
    - {
    - cache_file = sys.overrides.__getitem__(override_name) ;
    - }
    - else
    - {
    - cache_file = module_name ;
    - }
    -
    - cache_file = (path + cache_file + '.cache.js' ) ;
    -
    - //alert("cache " + cache_file + " " + module_name + " " + parent_module);
    -
    - /* already loaded? */
    - if (module_load_request[module_name])
    - {
    - if (module_load_request[module_name] >= 3 && parent_module != null)
    - {
    - //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';';
    - //pyjs_eval(onload_fn); /* set up the parent-module namespace */
    - }
    - return;
    - }
    - if (typeof (module_load_request[module_name]) == 'undefined')
    - {
    - module_load_request[module_name] = 1;
    - }
    -
    - /* following a load, this first executes the script
    - * "preparation" function MODULENAME_loaded_fn()
    - * and then sets up the loaded module in the namespace
    - * of the parent.
    - */
    -
    - onload_fn = ''; // module_name + "_loaded_fn();"
    -
    - if (parent_module != null)
    - {
    - //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';';
    - /*pmod = parent_module + '.' + module_name;
    - onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/
    - }
    -
    -
    - if (dynamic)
    - {
    - /* this one tacks the script onto the end of the DOM
    - */
    -
    - pyjs_load_script(cache_file, onload_fn, async);
    -
    - /* this one actually RUNS the script (eval) into the page.
    - my feeling is that this would be better for non-async
    - but i can't get it to work entirely yet.
    - */
    - /*pyjs_ajax_eval(cache_file, onload_fn, async);*/
    - }
    - else
    - {
    - if (module_name != "pyjslib" &&
    - module_name != "sys")
    - pyjs_eval(onload_fn);
    - }
    -
    - """)
    -
    -JS("""
    -function import_wait(proceed_fn, parent_mod, dynamic) {
    -
    - var data = '';
    - var element = $doc.createElement("div");
    - $doc.body.appendChild(element);
    - function write_dom(txt) {
    - element.innerHTML = txt + '<br />';
    - }
    -
    - var timeoutperiod = 1;
    - if (dynamic)
    - var timeoutperiod = 1;
    -
    - var wait = function() {
    -
    - var status = '';
    - for (l in module_load_request)
    - {
    - var m = module_load_request[l];
    - if (l == "sys" || l == 'pyjslib')
    - continue;
    - status += l + m + " ";
    - }
    -
    - //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
    - wait_count += 1;
    -
    - if (status == '')
    - {
    - setTimeout(wait, timeoutperiod);
    - return;
    - }
    -
    - for (l in module_load_request)
    - {
    - var m = module_load_request[l];
    - if (l == "sys" || l == 'pyjslib')
    - {
    - module_load_request[l] = 4;
    - continue;
    - }
    - if ((parent_mod != null) && (l == parent_mod))
    - {
    - if (m == 1)
    - {
    - setTimeout(wait, timeoutperiod);
    - return;
    - }
    - if (m == 2)
    - {
    - /* cheat and move app on to next stage */
    - module_load_request[l] = 3;
    - }
    - }
    - if (m == 1 || m == 2)
    - {
    - setTimeout(wait, timeoutperiod);
    - return;
    - }
    - if (m == 3)
    - {
    - //alert("waited for module " + l + ": loaded");
    - module_load_request[l] = 4;
    - mod_fn = modules[l];
    - }
    - }
    - //alert("module wait done");
    -
    - if (proceed_fn.importDone)
    - proceed_fn.importDone(proceed_fn);
    - else
    - proceed_fn();
    - }
    -
    - wait();
    -}
    -""")
    -
    -class Object:
    - pass
    -
    -object = Object
    -
    -class Modload:
    -
    - def __init__(self, path, app_modlist, app_imported_fn, dynamic,
    - parent_mod):
    - self.app_modlist = app_modlist
    - self.app_imported_fn = app_imported_fn
    - self.path = path
    - self.idx = 0;
    - self.dynamic = dynamic
    - self.parent_mod = parent_mod
    -
    - def next(self):
    -
    - for i in range(len(self.app_modlist[self.idx])):
    - app = self.app_modlist[self.idx][i]
    - import_module(self.path, self.parent_mod, app, self.dynamic, True);
    - self.idx += 1
    -
    - if self.idx >= len(self.app_modlist):
    - import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
    - else:
    - import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
    -
    -def get_module(module_name):
    - ev = "__mod = %s;" % module_name
    - JS("pyjs_eval(ev);")
    - return __mod
    -
    -def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
    - parent_mod=None):
    -
    - loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
    - loader.next()
    -
    -import sys
    -
    -class BaseException:
    -
    - name = "BaseException"
    -
    - def __init__(self, *args):
    - self.args = args
    -
    - def __str__(self):
    - if len(self.args) is 0:
    - return ''
    - elif len(self.args) is 1:
    - return repr(self.args[0])
    - return repr(self.args)
    -
    - def toString(self):
    - return str(self)
    -
    -class Exception(BaseException):
    -
    - name = "Exception"
    -
    -class TypeError(BaseException):
    - name = "TypeError"
    -
    -class StandardError(Exception):
    - name = "StandardError"
    -
    -class LookupError(StandardError):
    - name = "LookupError"
    -
    - def toString(self):
    - return self.name + ": " + self.args[0]
    -
    -class KeyError(LookupError):
    - name = "KeyError"
    -
    -class AttributeError(StandardError):
    -
    - name = "AttributeError"
    -
    - def toString(self):
    - return "AttributeError: %s of %s" % (self.args[1], self.args[0])
    -
    -JS("""
    -pyjslib.StopIteration = function () { };
    -pyjslib.StopIteration.prototype = new Error();
    -pyjslib.StopIteration.name = 'StopIteration';
    -pyjslib.StopIteration.message = 'StopIteration';
    -
    -pyjslib.String_find = function(sub, start, end) {
    - var pos=this.indexOf(sub, start);
    - if (pyjslib.isUndefined(end)) return pos;
    -
    - if (pos + sub.length>end) return -1;
    - return pos;
    -}
    -
    -pyjslib.String_join = function(data) {
    - var text="";
    -
    - if (pyjslib.isArray(data)) {
    - return data.join(this);
    - }
    - else if (pyjslib.isIteratable(data)) {
    - var iter=data.__iter__();
    - try {
    - text+=iter.next();
    - while (true) {
    - var item=iter.next();
    - text+=this + item;
    - }
    - }
    - catch (e) {
    - if (e != pyjslib.StopIteration) throw e;
    - }
    - }
    -
    - return text;
    -}
    -
    -pyjslib.String_isdigit = function() {
    - return (this.match(/^\d+$/g) != null);
    -}
    -
    -pyjslib.String_replace = function(old, replace, count) {
    - var do_max=false;
    - var start=0;
    - var new_str="";
    - var pos=0;
    -
    - if (!pyjslib.isString(old)) return this.__replace(old, replace);
    - if (!pyjslib.isUndefined(count)) do_max=true;
    -
    - while (start<this.length) {
    - if (do_max && !count--) break;
    -
    - pos=this.indexOf(old, start);
    - if (pos<0) break;
    -
    - new_str+=this.substring(start, pos) + replace;
    - start=pos+old.length;
    - }
    - if (start<this.length) new_str+=this.substring(start);
    -
    - return new_str;
    -}
    -
    -pyjslib.String_split = function(sep, maxsplit) {
    - var items=new pyjslib.List();
    - var do_max=false;
    - var subject=this;
    - var start=0;
    - var pos=0;
    -
    - if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) {
    - sep=" ";
    - subject=subject.strip();
    - subject=subject.replace(/\s+/g, sep);
    - }
    - else if (!pyjslib.isUndefined(maxsplit)) do_max=true;
    -
    - if (subject.length == 0) {
    - return items;
    - }
    -
    - while (start<subject.length) {
    - if (do_max && !maxsplit--) break;
    -
    - pos=subject.indexOf(sep, start);
    - if (pos<0) break;
    -
    - items.append(subject.substring(start, pos));
    - start=pos+sep.length;
    - }
    - if (start<=subject.length) items.append(subject.substring(start));
    -
    - return items;
    -}
    -
    -pyjslib.String___iter__ = function() {
    - var i = 0;
    - var s = this;
    - return {
    - 'next': function() {
    - if (i >= s.length) {
    - throw pyjslib.StopIteration;
    - }
    - return s.substring(i++, i, 1);
    - },
    - '__iter__': function() {
    - return this;
    - }
    - };
    -}
    -
    -pyjslib.String_strip = function(chars) {
    - return this.lstrip(chars).rstrip(chars);
    -}
    -
    -pyjslib.String_lstrip = function(chars) {
    - if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, "");
    -
    - return this.replace(new RegExp("^[" + chars + "]+"), "");
    -}
    -
    -pyjslib.String_rstrip = function(chars) {
    - if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, "");
    -
    - return this.replace(new RegExp("[" + chars + "]+$"), "");
    -}
    -
    -pyjslib.String_startswith = function(prefix, start) {
    - if (pyjslib.isUndefined(start)) start = 0;
    -
    - if (this.substring(start, prefix.length) == prefix) return true;
    - return false;
    -}
    -
    -pyjslib.abs = Math.abs;
    -
    -""")
    -
    -class Class:
    - def __init__(self, name):
    - self.name = name
    -
    - def __str___(self):
    - return self.name
    -
    -def eq(a,b):
    - JS("""
    - if (pyjslib.hasattr(a, "__cmp__")) {
    - return a.__cmp__(b) == 0;
    - } else if (pyjslib.hasattr(b, "__cmp__")) {
    - return b.__cmp__(a) == 0;
    - }
    - return a == b;
    - """)
    -
    -def cmp(a,b):
    - if hasattr(a, "__cmp__"):
    - return a.__cmp__(b)
    - elif hasattr(b, "__cmp__"):
    - return -b.__cmp__(a)
    - if a > b:
    - return 1
    - elif b > a:
    - return -1
    - else:
    - return 0
    -
    -def bool(v):
    - # this needs to stay in native code without any dependencies here,
    - # because this is used by if and while, we need to prevent
    - # recursion
    - JS("""
    - if (!v) return false;
    - switch(typeof v){
    - case 'boolean':
    - return v;
    - case 'object':
    - if (v.__nonzero__){
    - return v.__nonzero__();
    - }else if (v.__len__){
    - return v.__len__()>0;
    - }
    - return true;
    - }
    - return Boolean(v);
    - """)
    -
    -class List:
    - def __init__(self, data=None):
    - JS("""
    - this.l = [];
    - this.extend(data);
    - """)
    -
    - def append(self, item):
    - JS(""" this.l[this.l.length] = item;""")
    -
    - def extend(self, data):
    - JS("""
    - if (pyjslib.isArray(data)) {
    - n = this.l.length;
    - for (var i=0; i < data.length; i++) {
    - this.l[n+i]=data[i];
    - }
    - }
    - else if (pyjslib.isIteratable(data)) {
    - var iter=data.__iter__();
    - var i=this.l.length;
    - try {
    - while (true) {
    - var item=iter.next();
    - this.l[i++]=item;
    - }
    - }
    - catch (e) {
    - if (e != pyjslib.StopIteration) throw e;
    - }
    - }
    - """)
    -
    - def remove(self, value):
    - JS("""
    - var index=this.index(value);
    - if (index<0) return false;
    - this.l.splice(index, 1);
    - return true;
    - """)
    -
    - def index(self, value, start=0):
    - JS("""
    - var length=this.l.length;
    - for (var i=start; i<length; i++) {
    - if (this.l[i]==value) {
    - return i;
    - }
    - }
    - return -1;
    - """)
    -
    - 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):
    - JS("""
    - if (index<0) index = this.l.length + index;
    - var a = this.l[index];
    - this.l.splice(index, 1);
    - return a;
    - """)
    -
    - def __cmp__(self, l):
    - if not isinstance(l, List):
    - return -1
    - ll = len(self) - len(l)
    - if ll != 0:
    - return ll
    - for x in range(len(l)):
    - ll = cmp(self.__getitem__(x), l[x])
    - if ll != 0:
    - return ll
    - return 0
    -
    - def slice(self, lower, upper):
    - JS("""
    - if (upper==null) return pyjslib.List(this.l.slice(lower));
    - return pyjslib.List(this.l.slice(lower, upper));
    - """)
    -
    - def __getitem__(self, index):
    - JS("""
    - if (index<0) index = this.l.length + index;
    - return this.l[index];
    - """)
    -
    - def __setitem__(self, index, value):
    - JS(""" this.l[index]=value;""")
    -
    - def __delitem__(self, index):
    - JS(""" this.l.splice(index, 1);""")
    -
    - def __len__(self):
    - JS(""" return this.l.length;""")
    -
    - def __contains__(self, value):
    - return self.index(value) >= 0
    -
    - def __iter__(self):
    - JS("""
    - var i = 0;
    - var l = this.l;
    - return {
    - 'next': function() {
    - if (i >= l.length) {
    - throw pyjslib.StopIteration;
    - }
    - return l[i++];
    - },
    - '__iter__': function() {
    - return this;
    - }
    - };
    - """)
    -
    - def reverse(self):
    - JS(""" this.l.reverse();""")
    -
    - def sort(self, compareFunc=None, keyFunc=None, reverse=False):
    - if not compareFunc:
    - global cmp
    - compareFunc = cmp
    - if keyFunc and reverse:
    - def thisSort1(a,b):
    - return -compareFunc(keyFunc(a), keyFunc(b))
    - self.l.sort(thisSort1)
    - elif keyFunc:
    - def thisSort2(a,b):
    - return compareFunc(keyFunc(a), keyFunc(b))
    - self.l.sort(thisSort2)
    - elif reverse:
    - def thisSort3(a,b):
    - return -compareFunc(a, b)
    - self.l.sort(thisSort3)
    - else:
    - self.l.sort(compareFunc)
    -
    - def getArray(self):
    - """
    - Access the javascript Array that is used internally by this list
    - """
    - return self.l
    -
    - def __str__(self):
    - return repr(self)
    -
    -list = List
    -
    -class Tuple:
    - def __init__(self, data=None):
    - JS("""
    - this.l = [];
    - this.extend(data);
    - """)
    -
    - def append(self, item):
    - JS(""" this.l[this.l.length] = item;""")
    -
    - def extend(self, data):
    - JS("""
    - if (pyjslib.isArray(data)) {
    - n = this.l.length;
    - for (var i=0; i < data.length; i++) {
    - this.l[n+i]=data[i];
    - }
    - }
    - else if (pyjslib.isIteratable(data)) {
    - var iter=data.__iter__();
    - var i=this.l.length;
    - try {
    - while (true) {
    - var item=iter.next();
    - this.l[i++]=item;
    - }
    - }
    - catch (e) {
    - if (e != pyjslib.StopIteration) throw e;
    - }
    - }
    - """)
    -
    - def remove(self, value):
    - JS("""
    - var index=this.index(value);
    - if (index<0) return false;
    - this.l.splice(index, 1);
    - return true;
    - """)
    -
    - def index(self, value, start=0):
    - JS("""
    - var length=this.l.length;
    - for (var i=start; i<length; i++) {
    - if (this.l[i]==value) {
    - return i;
    - }
    - }
    - return -1;
    - """)
    -
    - 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):
    - JS("""
    - if (index<0) index = this.l.length + index;
    - var a = this.l[index];
    - this.l.splice(index, 1);
    - return a;
    - """)
    -
    - def __cmp__(self, l):
    - if not isinstance(l, Tuple):
    - return -1
    - ll = len(self) - len(l)
    - if ll != 0:
    - return ll
    - for x in range(len(l)):
    - ll = cmp(self.__getitem__(x), l[x])
    - if ll != 0:
    - return ll
    - return 0
    -
    - def slice(self, lower, upper):
    - JS("""
    - if (upper==null) return pyjslib.Tuple(this.l.slice(lower));
    - return pyjslib.Tuple(this.l.slice(lower, upper));
    - """)
    -
    - def __getitem__(self, index):
    - JS("""
    - if (index<0) index = this.l.length + index;
    - return this.l[index];
    - """)
    -
    - def __setitem__(self, index, value):
    - JS(""" this.l[index]=value;""")
    -
    - def __delitem__(self, index):
    - JS(""" this.l.splice(index, 1);""")
    -
    - def __len__(self):
    - JS(""" return this.l.length;""")
    -
    - def __contains__(self, value):
    - return self.index(value) >= 0
    -
    - def __iter__(self):
    - JS("""
    - var i = 0;
    - var l = this.l;
    - return {
    - 'next': function() {
    - if (i >= l.length) {
    - throw pyjslib.StopIteration;
    - }
    - return l[i++];
    - },
    - '__iter__': function() {
    - return this;
    - }
    - };
    - """)
    -
    - def reverse(self):
    - JS(""" this.l.reverse();""")
    -
    - def sort(self, compareFunc=None, keyFunc=None, reverse=False):
    - if not compareFunc:
    - global cmp
    - compareFunc = cmp
    - if keyFunc and reverse:
    - def thisSort1(a,b):
    - return -compareFunc(keyFunc(a), keyFunc(b))
    - self.l.sort(thisSort1)
    - elif keyFunc:
    - def thisSort2(a,b):
    - return compareFunc(keyFunc(a), keyFunc(b))
    - self.l.sort(thisSort2)
    - elif reverse:
    - def thisSort3(a,b):
    - return -compareFunc(a, b)
    - self.l.sort(thisSort3)
    - else:
    - self.l.sort(compareFunc)
    -
    - def getArray(self):
    - """
    - Access the javascript Array that is used internally by this list
    - """
    - return self.l
    -
    - def __str__(self):
    - return repr(self)
    -
    -tuple = Tuple
    -
    -
    -class Dict:
    - def __init__(self, data=None):
    - JS("""
    - this.d = {};
    -
    - if (pyjslib.isArray(data)) {
    - for (var i in data) {
    - var item=data[i];
    - this.__setitem__(item[0], item[1]);
    - //var sKey=pyjslib.hash(item[0]);
    - //this.d[sKey]=item[1];
    - }
    - }
    - else if (pyjslib.isIteratable(data)) {
    - var iter=data.__iter__();
    - try {
    - while (true) {
    - var item=iter.next();
    - this.__setitem__(item.__getitem__(0), item.__getitem__(1));
    - }
    - }
    - catch (e) {
    - if (e != pyjslib.StopIteration) throw e;
    - }
    - }
    - else if (pyjslib.isObject(data)) {
    - for (var key in data) {
    - this.__setitem__(key, data[key]);
    - }
    - }
    - """)
    -
    - def __setitem__(self, key, value):
    - JS("""
    - var sKey = pyjslib.hash(key);
    - this.d[sKey]=[key, value];
    - """)
    -
    - def __getitem__(self, key):
    - JS("""
    - var sKey = pyjslib.hash(key);
    - var value=this.d[sKey];
    - if (pyjslib.isUndefined(value)){
    - throw pyjslib.KeyError(key);
    - }
    - return value[1];
    - """)
    -
    - def __nonzero__(self):
    - JS("""
    - for (var i in this.d){
    - return true;
    - }
    - return false;
    - """)
    -
    - def __len__(self):
    - JS("""
    - var size=0;
    - for (var i in this.d) size++;
    - return size;
    - """)
    -
    - def has_key(self, key):
    - return self.__contains__(key)
    -
    - def __delitem__(self, key):
    - JS("""
    - var sKey = pyjslib.hash(key);
    - delete this.d[sKey];
    - """)
    -
    - def __contains__(self, key):
    - JS("""
    - var sKey = pyjslib.hash(key);
    - return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
    - """)
    -
    - def keys(self):
    - JS("""
    - var keys=new pyjslib.List();
    - for (var key in this.d) {
    - keys.append(this.d[key][0]);
    - }
    - return keys;
    - """)
    -
    - def values(self):
    - JS("""
    - var values=new pyjslib.List();
    - for (var key in this.d) values.append(this.d[key][1]);
    - return values;
    - """)
    -
    - def items(self):
    - JS("""
    - var items = new pyjslib.List();
    - for (var key in this.d) {
    - var kv = this.d[key];
    - items.append(new pyjslib.List(kv))
    - }
    - return items;
    - """)
    -
    - def __iter__(self):
    - return self.keys().__iter__()
    -
    - def iterkeys(self):
    - return self.__iter__()
    -
    - def itervalues(self):
    - return self.values().__iter__();
    -
    - def iteritems(self):
    - return self.items().__iter__();
    -
    - def setdefault(self, key, default_value):
    - if not self.has_key(key):
    - self[key] = default_value
    -
    - def get(self, key, default_=None):
    - if not self.has_key(key):
    - return default_
    - return self[key]
    -
    - def update(self, d):
    - for k,v in d.iteritems():
    - self[k] = v
    -
    - def getObject(self):
    - """
    - Return the javascript Object which this class uses to store
    - dictionary keys and values
    - """
    - return self.d
    -
    - def copy(self):
    - return Dict(self.items())
    -
    - def __str__(self):
    - return repr(self)
    -
    -dict = Dict
    -
    -# taken from mochikit: range( [start,] stop[, step] )
    -def range():
    - JS("""
    - var start = 0;
    - var stop = 0;
    - var step = 1;
    -
    - if (arguments.length == 2) {
    - start = arguments[0];
    - stop = arguments[1];
    - }
    - else if (arguments.length == 3) {
    - start = arguments[0];
    - stop = arguments[1];
    - step = arguments[2];
    - }
    - else if (arguments.length>0) stop = arguments[0];
    -
    - return {
    - 'next': function() {
    - if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
    - var rval = start;
    - start += step;
    - return rval;
    - },
    - '__iter__': function() {
    - return this;
    - }
    - }
    - """)
    -
    -def slice(object, lower, upper):
    - JS("""
    - if (pyjslib.isString(object)) {
    - if (lower < 0) {
    - lower = object.length + lower;
    - }
    - if (upper < 0) {
    - upper = object.length + upper;
    - }
    - if (pyjslib.isNull(upper)) upper=object.length;
    - return object.substring(lower, upper);
    - }
    - if (pyjslib.isObject(object) && object.slice)
    - return object.slice(lower, upper);
    -
    - return null;
    - """)
    -
    -def str(text):
    - JS("""
    - if (pyjslib.hasattr(text,"__str__")) {
    - return text.__str__();
    - }
    - return String(text);
    - """)
    -
    -def ord(x):
    - if(isString(x) and len(x) is 1):
    - JS("""
    - return x.charCodeAt(0);
    - """)
    - else:
    - JS("""
    - throw pyjslib.TypeError();
    - """)
    - return None
    -
    -def chr(x):
    - JS("""
    - return String.fromCharCode(x)
    - """)
    -
    -def is_basetype(x):
    - JS("""
    - var t = typeof(x);
    - return t == 'boolean' ||
    - t == 'function' ||
    - t == 'number' ||
    - t == 'string' ||
    - t == 'undefined'
    - ;
    - """)
    -
    -def get_pyjs_classtype(x):
    - JS("""
    - if (pyjslib.hasattr(x, "__class__"))
    - if (pyjslib.hasattr(x.__class__, "__new__"))
    - var src = x.__class__.__name__;
    - return src;
    - return null;
    - """)
    -
    -def repr(x):
    - """ Return the string representation of 'x'.
    - """
    - JS("""
    - if (x === null)
    - return "null";
    -
    - if (x === undefined)
    - return "undefined";
    -
    - var t = typeof(x);
    -
    - //alert("repr typeof " + t + " : " + x);
    -
    - if (t == "boolean")
    - return x.toString();
    -
    - if (t == "function")
    - return "<function " + x.toString() + ">";
    -
    - if (t == "number")
    - return x.toString();
    -
    - if (t == "string") {
    - if (x.indexOf("'") == -1)
    - return "'" + x + "'";
    - if (x.indexOf('"') == -1)
    - return '"' + x + '"';
    - var s = x.replace(new RegExp('"', "g"), '\\\\"');
    - return '"' + s + '"';
    - };
    -
    - if (t == "undefined")
    - return "undefined";
    -
    - // If we get here, x is an object. See if it's a Pyjamas class.
    -
    - if (!pyjslib.hasattr(x, "__init__"))
    - return "<" + x.toString() + ">";
    -
    - // Handle the common Pyjamas data types.
    -
    - var constructor = "UNKNOWN";
    -
    - constructor = pyjslib.get_pyjs_classtype(x);
    -
    - //alert("repr constructor: " + constructor);
    -
    - if (constructor == "Tuple") {
    - var contents = x.getArray();
    - var s = "(";
    - for (var i=0; i < contents.length; i++) {
    - s += pyjslib.repr(contents[i]);
    - if (i < contents.length - 1)
    - s += ", ";
    - };
    - s += ")"
    - return s;
    - };
    -
    - if (constructor == "List") {
    - var contents = x.getArray();
    - var s = "[";
    - for (var i=0; i < contents.length; i++) {
    - s += pyjslib.repr(contents[i]);
    - if (i < contents.length - 1)
    - s += ", ";
    - };
    - s += "]"
    - return s;
    - };
    -
    - if (constructor == "Dict") {
    - var keys = new Array();
    - for (var key in x.d)
    - keys.push(key);
    -
    - var s = "{";
    - for (var i=0; i<keys.length; i++) {
    - var key = keys[i]
    - s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]);
    - if (i < keys.length-1)
    - s += ", "
    - };
    - s += "}";
    - return s;
    - };
    -
    - // 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>";
    - """)
    -
    -def float(text):
    - JS("""
    - return parseFloat(text);
    - """)
    -
    -def int(text, radix=0):
    - JS("""
    - return parseInt(text, radix);
    - """)
    -
    -def len(object):
    - JS("""
    - if (object==null) return 0;
    - if (pyjslib.isObject(object) && object.__len__) return object.__len__();
    - return object.length;
    - """)
    -
    -def isinstance(object_, classinfo):
    - if pyjslib.isUndefined(object_):
    - return False
    - if not pyjslib.isObject(object_):
    -
    - return False
    - if _isinstance(classinfo, Tuple):
    - for ci in classinfo:
    - if isinstance(object_, ci):
    - return True
    - return False
    - else:
    - return _isinstance(object_, classinfo)
    -
    -def _isinstance(object_, classinfo):
    - if not pyjslib.isObject(object_):
    - return False
    - JS("""
    - if (object_.__class__){
    - var res = object_ instanceof classinfo.constructor;
    - return res;
    - }
    - return false;
    - """)
    -
    -def getattr(obj, name, default_):
    - JS("""
    - if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
    - if (pyjslib.isUndefined(default_)){
    - throw pyjslib.AttributeError(obj, name);
    - }else{
    - return default_;
    - }
    - }
    - if (!pyjslib.isFunction(obj[name])) return obj[name];
    - var fnwrap = function() {
    - var args = [];
    - for (var i = 0; i < arguments.length; i++) {
    - args.push(arguments[i]);
    - }
    - return obj[name].apply(obj,args);
    - }
    - fnwrap.__name__ = name;
    - return fnwrap;
    - """)
    -
    -def setattr(obj, name, value):
    - JS("""
    - if (!pyjslib.isObject(obj)) return null;
    -
    - obj[name] = value;
    -
    - """)
    -
    -def hasattr(obj, name):
    - JS("""
    - if (!pyjslib.isObject(obj)) return false;
    - if (pyjslib.isUndefined(obj[name])) return false;
    -
    - return true;
    - """)
    -
    -def dir(obj):
    - JS("""
    - var properties=new pyjslib.List();
    - for (property in obj) properties.append(property);
    - return properties;
    - """)
    -
    -def filter(obj, method, sequence=None):
    - # object context is LOST when a method is passed, hence object must be passed separately
    - # to emulate python behaviour, should generate this code inline rather than as a function call
    - items = []
    - if sequence is None:
    - sequence = method
    - method = obj
    -
    - for item in sequence:
    - if method(item):
    - items.append(item)
    - else:
    - for item in sequence:
    - if method.call(obj, item):
    - items.append(item)
    -
    - return items
    -
    -
    -def map(obj, method, sequence=None):
    - items = []
    -
    - if sequence is None:
    - sequence = method
    - method = obj
    -
    - for item in sequence:
    - items.append(method(item))
    - else:
    - for item in sequence:
    - items.append(method.call(obj, item))
    -
    - return items
    -
    -
    -def enumerate(sequence):
    - enumeration = []
    - nextIndex = 0
    - for item in sequence:
    - enumeration.append([nextIndex, item])
    - nextIndex = nextIndex + 1
    - return enumeration
    -
    -
    -def min(*sequence):
    - minValue = None
    - for item in sequence:
    - if minValue is None:
    - minValue = item
    - elif item < minValue:
    - minValue = item
    - return minValue
    -
    -
    -def max(*sequence):
    - maxValue = None
    - for item in sequence:
    - if maxValue is None:
    - maxValue = item
    - elif item > maxValue:
    - maxValue = item
    - return maxValue
    -
    -
    -next_hash_id = 0
    -
    -def hash(obj):
    - JS("""
    - if (obj == null) return null;
    -
    - if (obj.$H) return obj.$H;
    - if (obj.__hash__) return obj.__hash__();
    - if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
    -
    - obj.$H = ++pyjslib.next_hash_id;
    - return obj.$H;
    - """)
    -
    -
    -# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
    -def isObject(a):
    - JS("""
    - return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
    - """)
    -
    -def isFunction(a):
    - JS("""
    - return typeof a == 'function';
    - """)
    -
    -def isString(a):
    - JS("""
    - return typeof a == 'string';
    - """)
    -
    -def isNull(a):
    - JS("""
    - return typeof a == 'object' && !a;
    - """)
    -
    -def isArray(a):
    - JS("""
    - return pyjslib.isObject(a) && a.constructor == Array;
    - """)
    -
    -def isUndefined(a):
    - JS("""
    - return typeof a == 'undefined';
    - """)
    -
    -def isIteratable(a):
    - JS("""
    - return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
    - """)
    -
    -def isNumber(a):
    - JS("""
    - return typeof a == 'number' && isFinite(a);
    - """)
    -
    -def toJSObjects(x):
    - """
    - Convert the pyjs pythonic List and Dict objects into javascript Object and Array
    - objects, recursively.
    - """
    - if isArray(x):
    - JS("""
    - var result = [];
    - for(var k=0; k < x.length; k++) {
    - var v = x[k];
    - var tv = pyjslib.toJSObjects(v);
    - result.push(tv);
    - }
    - return result;
    - """)
    - if isObject(x):
    - if isinstance(x, Dict):
    - JS("""
    - var o = x.getObject();
    - var result = {};
    - for (var i in o) {
    - result[o[i][0].toString()] = o[i][1];
    - }
    - return pyjslib.toJSObjects(result)
    - """)
    - elif isinstance(x, List):
    - return toJSObjects(x.l)
    - elif hasattr(x, '__class__'):
    - # we do not have a special implementation for custom
    - # classes, just pass it on
    - return x
    - if isObject(x):
    - JS("""
    - var result = {};
    - for(var k in x) {
    - var v = x[k];
    - var tv = pyjslib.toJSObjects(v)
    - result[k] = tv;
    - }
    - return result;
    - """)
    - return x
    -
    -def printFunc(objs):
    - JS("""
    - if ($wnd.console==undefined) return;
    - var s = "";
    - for(var i=0; i < objs.length; i++) {
    - if(s != "") s += " ";
    - s += objs[i];
    - }
    - console.debug(s)
    - """)
    -
    -def type(clsname, bases=None, methods=None):
    - """ creates a class, derived from bases, with methods and variables
    - """
    -
    - JS(" var mths = {}; ")
    - if methods:
    - for k in methods.keys():
    - mth = methods[k]
    - JS(" mths[k] = mth; ")
    -
    - JS(" var bss = null; ")
    - if bases:
    - JS("bss = bases.l;")
    - JS(" return pyjs_type(clsname, bss, mths); ")
    -
    --- 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
    -loadpath = None
    -
    -stacktrace = None
    -
    -appname = None
    -
    -def setloadpath(lp):
    - global loadpath
    - loadpath = lp
    -
    -def setappname(an):
    - global appname
    - appname = an
    -
    -def getloadpath():
    - global loadpath
    - return loadpath
    -
    -def addoverride(module_name, path):
    - global overrides
    - overrides[module_name] = path
    -
    -def addstack(linedebug):
    - JS("""
    - if (pyjslib.bool((sys.stacktrace === null))) {
    - sys.stacktrace = new pyjslib.List([]);
    - }
    - sys.stacktrace.append(linedebug);
    - """)
    -def popstack():
    - JS("""
    - sys.stacktrace.pop()
    - """)
    -
    -def printstack():
    - JS("""
    - var res = '';
    -
    - var __l = sys.stacktrace.__iter__();
    - try {
    - while (true) {
    - var l = __l.next();
    - res += ( l + '\\n' ) ;
    - }
    - } catch (e) {
    - if (e != pyjslib.StopIteration) {
    - throw e;
    - }
    - }
    -
    - return res;
    - """)
    --- 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 @@
    -#!/usr/bin/env python
    -# Copyright 2006 James Tauber and contributors
    -#
    -# Licensed under the Apache License, Version 2.0 (the "License");
    -# you may not use this file except in compliance with the License.
    -# You may obtain a copy of the License at
    -#
    -# http://www.apache.org/licenses/LICENSE-2.0
    -#
    -# Unless required by applicable law or agreed to in writing, software
    -# distributed under the License is distributed on an "AS IS" BASIS,
    -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -# See the License for the specific language governing permissions and
    -# limitations under the License.
    -
    -
    -import sys
    -from types import StringType
    -import compiler
    -from compiler import ast
    -import os
    -import copy
    -
    -# the standard location for builtins (e.g. pyjslib) can be
    -# over-ridden by changing this. it defaults to sys.prefix
    -# so that on a system-wide install of pyjamas the builtins
    -# can be found in e.g. {sys.prefix}/share/pyjamas
    -#
    -# over-rides can be done by either explicitly modifying
    -# pyjs.prefix or by setting an environment variable, PYJSPREFIX.
    -
    -prefix = sys.prefix
    -
    -if os.environ.has_key('PYJSPREFIX'):
    - prefix = os.environ['PYJSPREFIX']
    -
    -# pyjs.path is the list of paths, just like sys.path, from which
    -# library modules will be searched for, for compile purposes.
    -# obviously we don't want to use sys.path because that would result
    -# in compiling standard python modules into javascript!
    -
    -path = [os.path.abspath('')]
    -
    -if os.environ.has_key('PYJSPATH'):
    - for p in os.environ['PYJSPATH'].split(os.pathsep):
    - p = os.path.abspath(p)
    - if os.path.isdir(p):
    - path.append(p)
    -
    -# this is the python function used to wrap native javascript
    -NATIVE_JS_FUNC_NAME = "JS"
    -
    -UU = ""
    -
    -PYJSLIB_BUILTIN_FUNCTIONS=("cmp",
    - "map",
    - "filter",
    - "dir",
    - "getattr",
    - "setattr",
    - "hasattr",
    - "int",
    - "float",
    - "str",
    - "repr",
    - "range",
    - "len",
    - "hash",
    - "abs",
    - "ord",
    - "chr",
    - "enumerate",
    - "min",
    - "max",
    - "bool",
    - "type",
    - "isinstance")
    -
    -PYJSLIB_BUILTIN_CLASSES=("BaseException",
    - "Exception",
    - "StandardError",
    - "StopIteration",
    - "AttributeError",
    - "TypeError",
    - "KeyError",
    - "LookupError",
    - "list",
    - "dict",
    - "object",
    - "tuple",
    - )
    -
    -def pyjs_builtin_remap(name):
    - # XXX HACK!
    - if name == 'list':
    - name = 'List'
    - if name == 'object':
    - name = '__Object'
    - if name == 'dict':
    - name = 'Dict'
    - if name == 'tuple':
    - name = 'Tuple'
    - return name
    -
    -# XXX: this is a hack: these should be dealt with another way
    -# however, console is currently the only global name which is causing
    -# problems.
    -PYJS_GLOBAL_VARS=("console")
    -
    -# This is taken from the django project.
    -# Escape every ASCII character with a value less than 32.
    -JS_ESCAPES = (
    - ('\\', r'\x5C'),
    - ('\'', r'\x27'),
    - ('"', r'\x22'),
    - ('>', r'\x3E'),
    - ('<', r'\x3C'),
    - ('&', r'\x26'),
    - (';', r'\x3B')
    - ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)])
    -
    -def escapejs(value):
    - """Hex encodes characters for use in JavaScript strings."""
    - for bad, good in JS_ESCAPES:
    - value = value.replace(bad, good)
    - return value
    -
    -def uuprefix(name, leave_alone=0):
    - name = name.split(".")
    - name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:])
    - return '.'.join(name)
    -
    -class Klass:
    -
    - klasses = {}
    -
    - def __init__(self, name, name_):
    - self.name = name
    - self.name_ = name_
    - self.klasses[name] = self
    - self.functions = set()
    -
    - def set_base(self, base_name):
    - self.base = self.klasses.get(base_name)
    -
    - def add_function(self, function_name):
    - self.functions.add(function_name)
    -
    -
    -class TranslationError(Exception):
    - def __init__(self, message, node):
    - self.message = "line %s:\n%s\n%s" % (node.lineno, message, node)
    -
    - def __str__(self):
    - return self.message
    -
    -def strip_py(name):
    - return name
    -
    -def mod_var_name_decl(raw_module_name):
    - """ function to get the last component of the module e.g.
    - pyjamas.ui.DOM into the "namespace". i.e. doing
    - "import pyjamas.ui.DOM" actually ends up with _two_
    - variables - one pyjamas.ui.DOM, the other just "DOM".
    - but "DOM" is actually local, hence the "var" prefix.
    -
    - for PyV8, this might end up causing problems - we'll have
    - to see: gen_mod_import and mod_var_name_decl might have
    - to end up in a library-specific module, somewhere.
    - """
    - name = raw_module_name.split(".")
    - if len(name) == 1:
    - return ''
    - child_name = name[-1]
    - return "var %s = %s;\n" % (child_name, raw_module_name)
    -
    -def gen_mod_import(parentName, importName, dynamic=1):
    - #pyjs_ajax_eval("%(n)s.cache.js", null, true);
    - return """
    - pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false);
    - """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \
    - mod_var_name_decl(importName)
    -
    -class Translator:
    -
    - def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output,
    - dynamic=0, optimize=False,
    - findFile=None):
    -
    - if module_name:
    - self.module_prefix = module_name + "."
    - else:
    - self.module_prefix = ""
    - self.raw_module_name = raw_module_name
    - src = src.replace("\r\n", "\n")
    - src = src.replace("\n\r", "\n")
    - src = src.replace("\r", "\n")
    - self.src = src.split("\n")
    - self.debug = debug
    - self.imported_modules = []
    - self.imported_modules_as = []
    - self.imported_js = set()
    - self.top_level_functions = set()
    - self.top_level_classes = set()
    - self.top_level_vars = set()
    - self.local_arg_stack = [[]]
    - self.output = output
    - self.imported_classes = {}
    - self.method_imported_globals = set()
    - self.method_self = None
    - self.nextTupleAssignID = 1
    - self.dynamic = dynamic
    - self.optimize = optimize
    - self.findFile = findFile
    -
    - if module_name.find(".") >= 0:
    - vdec = ''
    - else:
    - vdec = 'var '
    - print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name)
    -
    - print >>self.output, " if("+module_name+".__was_initialized__) return;"
    - print >>self.output, " "+UU+module_name+".__was_initialized__ = true;"
    - print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn)
    - print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name)
    -
    - decl = mod_var_name_decl(raw_module_name)
    - if decl:
    - print >>self.output, decl
    -
    -
    - if self.debug:
    - haltException = self.module_prefix + "HaltException"
    - print >>self.output, haltException + ' = function () {'
    - print >>self.output, ' this.message = "Program Halted";'
    - print >>self.output, ' this.name = "' + haltException + '";'
    - print >>self.output, '}'
    - print >>self.output, ''
    - print >>self.output, haltException + ".prototype.__str__ = function()"
    - print >>self.output, '{'
    - print >>self.output, 'return this.message ;'
    - print >>self.output, '}'
    -
    - print >>self.output, haltException + ".prototype.toString = function()"
    - print >>self.output, '{'
    - print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";'
    - print >>self.output, '}'
    -
    - isHaltFunction = self.module_prefix + "IsHaltException"
    - print >>self.output, """
    - %s = function (s) {
    - var suffix="HaltException";
    - if (s.length < suffix.length) {
    - //alert(s + " " + suffix);
    - return false;
    - } else {
    - var ss = s.substring(s.length, (s.length - suffix.length));
    - //alert(s + " " + suffix + " " + ss);
    - return ss == suffix;
    - }
    - }
    - """ % isHaltFunction
    - for child in mod.node:
    - if isinstance(child, ast.Function):
    - self.top_level_functions.add(child.name)
    - elif isinstance(child, ast.Class):
    - self.top_level_classes.add(child.name)
    -
    - for child in mod.node:
    - if isinstance(child, ast.Function):
    - self._function(child, False)
    - elif isinstance(child, ast.Class):
    - self._class(child)
    - elif isinstance(child, ast.Import):
    - importName = child.names[0][0]
    - if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
    - pass
    - elif importName.endswith('.js'):
    - self.imported_js.add(importName)
    - else:
    - self.add_imported_module(strip_py(importName))
    - elif isinstance(child, ast.From):
    - if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
    - pass
    - else:
    - self.add_imported_module(child.modname)
    - self._from(child)
    - elif isinstance(child, ast.Discard):
    - self._discard(child, None)
    - elif isinstance(child, ast.Assign):
    - self._assign(child, None, True)
    - elif isinstance(child, ast.AugAssign):
    - self._augassign(child, None)
    - elif isinstance(child, ast.If):
    - self._if(child, None)
    - elif isinstance(child, ast.For):
    - self._for(child, None)
    - elif isinstance(child, ast.While):
    - self._while(child, None)
    - elif isinstance(child, ast.Subscript):
    - self._subscript_stmt(child, None)
    - elif isinstance(child, ast.Global):
    - self._global(child, None)
    - elif isinstance(child, ast.Printnl):
    - self._print(child, None)
    - elif isinstance(child, ast.Print):
    - self._print(child, None)
    - elif isinstance(child, ast.TryExcept):
    - self._tryExcept(child, None)
    - elif isinstance(child, ast.Raise):
    - self._raise(child, None)
    - elif isinstance(child, ast.Stmt):
    - self._stmt(child, None)
    - else:
    - raise TranslationError("unsupported type (in __init__)", child)
    -
    - # Initialize all classes for this module
    - #print >> self.output, "__"+self.modpfx()+\
    - # "classes_initialize = function() {\n"
    - #for className in self.top_level_classes:
    - # print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();"
    - #print >> self.output, "};\n"
    -
    - print >> self.output, "return this;\n"
    - print >> self.output, "}; /* end %s */ \n" % module_name
    -
    - def module_imports(self):
    - return self.imported_modules + self.imported_modules_as
    -
    - def add_local_arg(self, varname):
    - local_vars = self.local_arg_stack[-1]
    - if varname not in local_vars:
    - local_vars.append(varname)
    -
    - def add_imported_module(self, importName):
    -
    - if importName in self.imported_modules:
    - return
    - self.imported_modules.append(importName)
    - name = importName.split(".")
    - if len(name) != 1:
    - # add the name of the module to the namespace,
    - # but don't add the short name to imported_modules
    - # because then the short name would be attempted to be
    - # added to the dependencies, and it's half way up the
    - # module import directory structure!
    - child_name = name[-1]
    - self.imported_modules_as.append(child_name)
    - print >> self.output, gen_mod_import(self.raw_module_name,
    - strip_py(importName),
    - self.dynamic)
    -
    - def _default_args_handler(self, node, arg_names, current_klass,
    - output=None):
    - if len(node.defaults):
    - output = output or self.output
    - default_pos = len(arg_names) - len(node.defaults)
    - if arg_names and arg_names[0] == self.method_self:
    - default_pos -= 1
    - for default_node in node.defaults:
    - if isinstance(default_node, ast.Const):
    - default_value = self._const(default_node)
    - elif isinstance(default_node, ast.Name):
    - default_value = self._name(default_node, current_klass)
    - elif isinstance(default_node, ast.UnarySub):
    - default_value = self._unarysub(default_node, current_klass)
    - else:
    - raise TranslationError("unsupported type (in _method)", default_node)
    -
    - default_name = arg_names[default_pos]
    - default_pos += 1
    - print >> output, " if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value)
    -
    - def _varargs_handler(self, node, varargname, arg_names, current_klass):
    - print >>self.output, " var", varargname, '= new pyjslib.Tuple();'
    - print >>self.output, " for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {"
    - print >>self.output, " var __arg = arguments[__va_arg];"
    - print >>self.output, " "+varargname+".append(__arg);"
    - print >>self.output, " }"
    -
    - def _kwargs_parser(self, node, function_name, arg_names, current_klass):
    - if len(node.defaults) or node.kwargs:
    - default_pos = len(arg_names) - len(node.defaults)
    - if arg_names and arg_names[0] == self.method_self:
    - default_pos -= 1
    - print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {"
    - for default_node in node.defaults:
    - default_value = self.expr(default_node, current_klass)
    -# if isinstance(default_node, ast.Const):
    -# default_value = self._const(default_node)
    -# elif isinstance(default_node, ast.Name):
    -# default_value = self._name(default_node)
    -# elif isinstance(default_node, ast.UnarySub):
    -# default_value = self._unarysub(default_node, current_klass)
    -# else:
    -# raise TranslationError("unsupported type (in _method)", default_node)
    -
    - default_name = arg_names[default_pos]
    - print >>self.output, " if (typeof %s == 'undefined')"%(default_name)
    - print >>self.output, " %s=__kwargs.%s;"% (default_name, default_name)
    - default_pos += 1
    -
    - #self._default_args_handler(node, arg_names, current_klass)
    - if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"]
    - print >>self.output, " var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";"
    - if node.varargs:
    - self._varargs_handler(node, "__args", arg_names, current_klass)
    - print >>self.output, " __r.push.apply(__r, __args.getArray())"
    - print >>self.output, " return __r;"
    - print >>self.output, "};"
    -
    - def _function(self, node, local=False):
    - if local:
    - function_name = node.name
    - self.add_local_arg(function_name)
    - else:
    - function_name = UU + self.modpfx() + node.name
    -
    - arg_names = list(node.argnames)
    - normal_arg_names = list(arg_names)
    - if node.kwargs: kwargname = normal_arg_names.pop()
    - if node.varargs: varargname = normal_arg_names.pop()
    - declared_arg_names = list(normal_arg_names)
    - if node.kwargs: declared_arg_names.append(kwargname)
    -
    - function_args = "(" + ", ".join(declared_arg_names) + ")"
    - print >>self.output, "%s = function%s {" % (function_name, function_args)
    - self._default_args_handler(node, normal_arg_names, None)
    -
    - local_arg_names = normal_arg_names + declared_arg_names
    -
    - if node.varargs:
    - self._varargs_handler(node, varargname, declared_arg_names, None)
    - local_arg_names.append(varargname)
    -
    - # stack of local variable names for this function call
    - self.local_arg_stack.append(local_arg_names)
    -
    - for child in node.code:
    - self._stmt(child, None)
    -
    - # remove the top local arg names
    - self.local_arg_stack.pop()
    -
    - # we need to return null always, so it is not undefined
    - lastStmt = [p for p in node.code][-1]
    - if not isinstance(lastStmt, ast.Return):
    - if not self._isNativeFunc(lastStmt):
    - print >>self.output, " return null;"
    -
    - print >>self.output, "};"
    - print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name)
    -
    -
    - self._kwargs_parser(node, function_name, normal_arg_names, None)
    -
    -
    - def _return(self, node, current_klass):
    - expr = self.expr(node.value, current_klass)
    - # in python a function call always returns None, so we do it
    - # here too
    - print >>self.output, " return " + expr + ";"
    -
    -
    - def _break(self, node, current_klass):
    - print >>self.output, " break;"
    -
    -
    - def _continue(self, node, current_klass):
    - print >>self.output, " continue;"
    -
    -
    - def _callfunc(self, v, current_klass):
    -
    - if isinstance(v.node, ast.Name):
    - if v.node.name in self.top_level_functions:
    - call_name = self.modpfx() + v.node.name
    - elif v.node.name in self.top_level_classes:
    - call_name = self.modpfx() + v.node.name
    - elif self.imported_classes.has_key(v.node.name):
    - call_name = self.imported_classes[v.node.name] + '.' + v.node.name
    - elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS:
    - call_name = 'pyjslib.' + v.node.name
    - elif v.node.name in PYJSLIB_BUILTIN_CLASSES:
    - name = pyjs_builtin_remap(v.node.name)
    - call_name = 'pyjslib.' + name
    - elif v.node.name == "callable":
    - call_name = "pyjslib.isFunction"
    - else:
    - call_name = v.node.name
    - call_args = []
    - elif isinstance(v.node, ast.Getattr):
    - attr_name = v.node.attrname
    -
    - if isinstance(v.node.expr, ast.Name):
    - call_name = self._name2(v.node.expr, current_klass, attr_name)
    - call_args = []
    - elif isinstance(v.node.expr, ast.Getattr):
    - call_name = self._getattr2(v.node.expr, current_klass, attr_name)
    - call_args = []
    - elif isinstance(v.node.expr, ast.CallFunc):
    - call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname
    - call_args = []
    - elif isinstance(v.node.expr, ast.Subscript):
    - call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname
    - call_args = []
    - elif isinstance(v.node.expr, ast.Const):
    - call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname
    - call_args = []
    - else:
    - raise TranslationError("unsupported type (in _callfunc)", v.node.expr)
    - else:
    - raise TranslationError("unsupported type (in _callfunc)", v.node)
    -
    - call_name = strip_py(call_name)
    -
    - kwargs = []
    - star_arg_name = None
    - if v.star_args:
    - star_arg_name = self.expr(v.star_args, current_klass)
    -
    - for ch4 in v.args:
    - if isinstance(ch4, ast.Keyword):
    - kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass)
    - kwargs.append(kwarg)
    - else:
    - arg = self.expr(ch4, current_klass)
    - call_args.append(arg)
    -
    - if kwargs:
    - fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args)
    - else:
    - fn_args = ", ".join(call_args)
    -
    - if kwargs or star_arg_name:
    - if not star_arg_name:
    - star_arg_name = 'null'
    - try: call_this, method_name = call_name.rsplit(".", 1)
    - except ValueError:
    - # Must be a function call ...
    - return ("pyjs_kwargs_function_call("+call_name+", "
    - + star_arg_name
    - + ", ["+fn_args+"]"
    - + ")" )
    - else:
    - return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', "
    - + star_arg_name
    - + ", ["+fn_args+"]"
    - + ")")
    - else:
    - return call_name + "(" + ", ".join(call_args) + ")"
    -
    - def _print(self, node, current_klass):
    - if self.optimize:
    - return
    - call_args = []
    - for ch4 in node.nodes:
    - arg = self.expr(ch4, current_klass)
    - call_args.append(arg)
    -
    - print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");"
    -
    - def _tryExcept(self, node, current_klass):
    - if len(node.handlers) != 1:
    - raise TranslationError("except statements in this form are" +
    - " not supported", node)
    -
    - expr = node.handlers[0][0]
    - as_ = node.handlers[0][1]
    - if as_:
    - errName = as_.name
    - else:
    - errName = 'err'
    -
    - # XXX TODO: check that this should instead be added as a _separate_
    - # local scope, temporary to the function. oh dearie me.
    - self.add_local_arg(errName)
    -
    - print >>self.output, " try {"
    - for stmt in node.body.nodes:
    - self._stmt(stmt, current_klass)
    - print >> self.output, " } catch(%s) {" % errName
    - if expr:
    - l = []
    - if isinstance(expr, ast.Tuple):
    - for x in expr.nodes:
    - l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass)))
    - else:
    - l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ]
    - print >> self.output, " if(%s) {" % '||\n\t\t'.join(l)
    - for stmt in node.handlers[0][2]:
    - self._stmt(stmt, current_klass)
    - if expr:
    - #print >> self.output, "} else { throw(%s); } " % errName
    - print >> self.output, "}"
    - if node.else_ != None:
    - print >>self.output, " } finally {"
    - for stmt in node.else_:
    - self._stmt(stmt, current_klass)
    - print >>self.output, " }"
    -
    - # XXX: change use_getattr to True to enable "strict" compilation
    - # but incurring a 100% performance penalty. oops.
    - def _getattr(self, v, current_klass, use_getattr=False):
    - attr_name = v.attrname
    - if isinstance(v.expr, ast.Name):
    - obj = self._name(v.expr, current_klass, return_none_for_module=True)
    - if obj == None and v.expr.name in self.module_imports():
    - # XXX TODO: distinguish between module import classes
    - # and variables. right now, this is a hack to get
    - # the sys module working.
    - #if v.expr.name == 'sys':
    - return v.expr.name+'.'+attr_name
    - #return v.expr.name+'.__'+attr_name+'.prototype.__class__'
    - if not use_getattr or attr_name == '__class__' or \
    - attr_name == '__name__':
    - return obj + "." + attr_name
    - return "pyjslib.getattr(%s, '%s')" % (obj, attr_name)
    - elif isinstance(v.expr, ast.Getattr):
    - return self._getattr(v.expr, current_klass) + "." + attr_name
    - elif isinstance(v.expr, ast.Subscript):
    - return self._subscript(v.expr, self.modpfx()) + "." + attr_name
    - elif isinstance(v.expr, ast.CallFunc):
    - return self._callfunc(v.expr, self.modpfx()) + "." + attr_name
    - else:
    - raise TranslationError("unsupported type (in _getattr)", v.expr)
    -
    -
    - def modpfx(self):
    - return strip_py(self.module_prefix)
    -
    - def _name(self, v, current_klass, top_level=False,
    - return_none_for_module=False):
    -
    - if v.name == 'ilikesillynamesfornicedebugcode':
    - print top_level, current_klass, repr(v)
    - print self.top_level_vars
    - print self.top_level_functions
    - print self.local_arg_stack
    - print "error..."
    -
    - local_var_names = None
    - las = len(self.local_arg_stack)
    - if las > 0:
    - local_var_names = self.local_arg_stack[-1]
    -
    - if v.name == "True":
    - return "true"
    - elif v.name == "False":
    - return "false"
    - elif v.name == "None":
    - return "null"
    - elif v.name == '__name__' and current_klass is None:
    - return self.modpfx() + v.name
    - elif v.name == self.method_self:
    - return "this"
    - elif v.name in self.top_level_functions:
    - return UU+self.modpfx() + v.name
    - elif v.name in self.method_imported_globals:
    - return UU+self.modpfx() + v.name
    - elif not current_klass and las == 1 and v.name in self.top_level_vars:
    - return UU+self.modpfx() + v.name
    - elif v.name in local_var_names:
    - return v.name
    - elif self.imported_classes.has_key(v.name):
    - return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__"
    - elif v.name in self.top_level_classes:
    - return UU+self.modpfx() + "__" + v.name + ".prototype.__class__"
    - elif v.name in self.module_imports() and return_none_for_module:
    - return None
    - elif v.name in PYJSLIB_BUILTIN_CLASSES:
    - return "pyjslib." + pyjs_builtin_remap( v.name )
    - elif current_klass:
    - if v.name not in local_var_names and \
    - v.name not in self.top_level_vars and \
    - v.name not in PYJS_GLOBAL_VARS and \
    - v.name not in self.top_level_functions:
    -
    - cls_name = current_klass
    - if hasattr(cls_name, "name"):
    - cls_name_ = cls_name.name_
    - cls_name = cls_name.name
    - else:
    - cls_name_ = current_klass + "_" # XXX ???
    - name = UU+cls_name_ + ".prototype.__class__." \
    - + v.name
    - if v.name == 'listener':
    - name = 'listener+' + name
    - return name
    -
    - return v.name
    -
    - def _name2(self, v, current_klass, attr_name):
    - obj = v.name
    -
    - if obj in self.method_imported_globals:
    - call_name = UU+self.modpfx() + obj + "." + attr_name
    - elif self.imported_classes.has_key(obj):
    - #attr_str = ""
    - #if attr_name != "__init__":
    - attr_str = ".prototype.__class__." + attr_name
    - call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str
    - elif obj in self.module_imports():
    - call_name = obj + "." + attr_name
    - elif obj[0] == obj[0].upper(): # XXX HACK ALERT
    - call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name
    - else:
    - call_name = UU+self._name(v, current_klass) + "." + attr_name
    -
    - return call_name
    -
    -
    - def _getattr2(self, v, current_klass, attr_name):
    - if isinstance(v.expr, ast.Getattr):
    - call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name)
    - elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports():
    - call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name
    - else:
    - obj = self.expr(v.expr, current_klass)
    - call_name = obj + "." + v.attrname + "." + attr_name
    -
    - return call_name
    -
    -
    - def _class(self, node):
    - """
    - Handle a class definition.
    -
    - In order to translate python semantics reasonably well, the following
    - structure is used:
    -
    - A special object is created for the class, which inherits attributes
    - from the superclass, or Object if there's no superclass. This is the
    - class object; the object which you refer to when specifying the
    - class by name. Static, class, and unbound methods are copied
    - from the superclass object.
    -
    - A special constructor function is created with the same name as the
    - class, which is used to create instances of that class.
    -
    - A javascript class (e.g. a function with a prototype attribute) is
    - created which is the javascript class of created instances, and
    - which inherits attributes from the class object. Bound methods are
    - copied from the superclass into this class rather than inherited,
    - because the class object contains unbound, class, and static methods
    - that we don't necessarily want to inherit.
    -
    - The type of a method can now be determined by inspecting its
    - static_method, unbound_method, class_method, or instance_method
    - attribute; only one of these should be true.
    -
    - Much of this work is done in pyjs_extend, is pyjslib.py
    - """
    - class_name = self.modpfx() + uuprefix(node.name, 1)
    - class_name_ = self.modpfx() + uuprefix(node.name)
    - current_klass = Klass(class_name, class_name_)
    - init_method = None
    - for child in node.code:
    - if isinstance(child, ast.Function):
    - current_klass.add_function(child.name)
    - if child.name == "__init__":
    - init_method = child
    -
    -
    - if len(node.bases) == 0:
    - base_class = "pyjslib.__Object"
    - elif len(node.bases) == 1:
    - if isinstance(node.bases[0], ast.Name):
    - if self.imported_classes.has_key(node.bases[0].name):
    - base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name
    - base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name
    - else:
    - base_class_ = self.modpfx() + "__" + node.bases[0].name
    - base_class = self.modpfx() + node.bases[0].name
    - elif isinstance(node.bases[0], ast.Getattr):
    - # the bases are not in scope of the class so do not
    - # pass our class to self._name
    - base_class_ = self._name(node.bases[0].expr, None) + \
    - ".__" + node.bases[0].attrname
    - base_class = self._name(node.bases[0].expr, None) + \
    - "." + node.bases[0].attrname
    - else:
    - raise TranslationError("unsupported type (in _class)", node.bases[0])
    -
    - current_klass.set_base(base_class)
    - else:
    - raise TranslationError("more than one base (in _class)", node)
    -
    - print >>self.output, UU+class_name_ + " = function () {"
    - # call superconstructor
    - #if base_class:
    - # print >>self.output, " __" + base_class + ".call(this);"
    - print >>self.output, "}"
    -
    - if not init_method:
    - init_method = ast.Function([], "__init__", ["self"], [], 0, None, [])
    - #self._method(init_method, current_klass, class_name)
    -
    - # Generate a function which constructs the object
    - clsfunc = ast.Function([],
    - node.name,
    - init_method.argnames[1:],
    - init_method.defaults,
    - init_method.flags,
    - None,
    - [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const(
    -# I attempted lazy initialization, but then you can't access static class members
    -# " if(!__"+base_class+".__was_initialized__)"+
    -# " __" + class_name + "_initialize();\n" +
    - " var instance = new " + UU + class_name_ + "();\n" +
    - " if(instance.__init__) instance.__init__.apply(instance, arguments);\n" +
    - " return instance;"
    - )]))])
    -
    - self._function(clsfunc, False)
    - print >>self.output, UU+class_name_ + ".__initialize__ = function () {"
    - print >>self.output, " if("+UU+class_name_+".__was_initialized__) return;"
    - print >>self.output, " "+UU+class_name_+".__was_initialized__ = true;"
    - cls_obj = UU+class_name_ + '.prototype.__class__'
    -
    - if class_name == "pyjslib.__Object":
    - print >>self.output, " "+cls_obj+" = {};"
    - else:
    - if base_class and base_class not in ("object", "pyjslib.__Object"):
    - print >>self.output, " if(!"+UU+base_class_+".__was_initialized__)"
    - print >>self.output, " "+UU+base_class_+".__initialize__();"
    - print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");"
    - else:
    - print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);"
    -
    - print >>self.output, " "+cls_obj+".__new__ = "+UU+class_name+";"
    - print >>self.output, " "+cls_obj+".__name__ = '"+UU+node.name+"';"
    -
    - for child in node.code:
    - if isinstance(child, ast.Pass):
    - pass
    - elif isinstance(child, ast.Function):
    - self._method(child, current_klass, class_name, class_name_)
    - elif isinstance(child, ast.Assign):
    - self.classattr(child, current_klass)
    - elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const):
    - # Probably a docstring, turf it
    - pass
    - else:
    - raise TranslationError("unsupported type (in _class)", child)
    - print >>self.output, "}"
    -
    - print >> self.output, class_name_+".__initialize__();"
    -
    -
    - def classattr(self, node, current_klass):
    - self._assign(node, current_klass, True)
    -
    - def _raise(self, node, current_klass):
    - if node.expr2:
    - raise TranslationError("More than one expression unsupported",
    - node)
    - print >> self.output, "throw (%s);" % self.expr(
    - node.expr1, current_klass)
    -
    - def _method(self, node, current_klass, class_name, class_name_):
    - # reset global var scope
    - self.method_imported_globals = set()
    -
    - arg_names = list(node.argnames)
    -
    - classmethod = False
    - staticmethod = False
    - if node.decorators:
    - for d in node.decorators:
    - if d.name == "classmethod":
    - classmethod = True
    - elif d.name == "staticmethod":
    - staticmethod = True
    -
    - if staticmethod:
    - staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno)
    - self._function(staticfunc, True)
    - print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";";
    - print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;";
    - return
    - else:
    - if len(arg_names) == 0:
    - raise TranslationError("methods must take an argument 'self' (in _method)", node)
    - self.method_self = arg_names[0]
    -
    - #if not classmethod and arg_names[0] != "self":
    - # raise TranslationError("first arg not 'self' (in _method)", node)
    -
    - normal_arg_names = arg_names[1:]
    - if node.kwargs: kwargname = normal_arg_names.pop()
    - if node.varargs: varargname = normal_arg_names.pop()
    - declared_arg_names = list(normal_arg_names)
    - if node.kwargs: declared_arg_names.append(kwargname)
    -
    - function_args = "(" + ", ".join(declared_arg_names) + ")"
    -
    - if classmethod:
    - fexpr = UU + class_name_ + ".prototype.__class__." + node.name
    - else:
    - fexpr = UU + class_name_ + ".prototype." + node.name
    - print >>self.output, " "+fexpr + " = function" + function_args + " {"
    -
    - # default arguments
    - self._default_args_handler(node, normal_arg_names, current_klass)
    -
    - local_arg_names = normal_arg_names + declared_arg_names
    -
    - if node.varargs:
    - self._varargs_handler(node, varargname, declared_arg_names, current_klass)
    - local_arg_names.append(varargname)
    -
    -
    - # stack of local variable names for this function call
    - self.local_arg_stack.append(local_arg_names)
    -
    - for child in node.code:
    - self._stmt(child, current_klass)
    -
    - # remove the top local arg names
    - self.local_arg_stack.pop()
    -
    - print >>self.output, " };"
    -
    - self._kwargs_parser(node, fexpr, normal_arg_names, current_klass)
    -
    - if classmethod:
    - # Have to create a version on the instances which automatically passes the
    - # class as "self"
    - altexpr = UU + class_name_ + ".prototype." + node.name
    - print >>self.output, " "+altexpr + " = function() {"
    - print >>self.output, " return " + fexpr + ".apply(this.__class__, arguments);"
    - print >>self.output, " };"
    - print >>self.output, " "+fexpr+".class_method = true;"
    - print >>self.output, " "+altexpr+".instance_method = true;"
    - else:
    - # For instance methods, we need an unbound version in the class object
    - altexpr = UU + class_name_ + ".prototype.__class__." + node.name
    - print >>self.output, " "+altexpr + " = function() {"
    - print >>self.output, " return " + fexpr + ".call.apply("+fexpr+", arguments);"
    - print >>self.output, " };"
    - print >>self.output, " "+altexpr+".unbound_method = true;"
    - print >>self.output, " "+fexpr+".instance_method = true;"
    - print >>self.output, " "+altexpr+".__name__ = '%s';" % node.name
    -
    - print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \
    - (node.name, node.name)
    -
    - if node.kwargs or len(node.defaults):
    - print >>self.output, " "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;"
    -
    - self.method_self = None
    - self.method_imported_globals = set()
    -
    - def _isNativeFunc(self, node):
    - if isinstance(node, ast.Discard):
    - if isinstance(node.expr, ast.CallFunc):
    - if isinstance(node.expr.node, ast.Name) and \
    - node.expr.node.name == NATIVE_JS_FUNC_NAME:
    - return True
    - return False
    -
    - def _stmt(self, node, current_klass):
    - debugStmt = self.debug and not self._isNativeFunc(node)
    - if debugStmt:
    - print >>self.output, ' try {'
    -
    - if isinstance(node, ast.Return):
    - self._return(node, current_klass)
    - elif isinstance(node, ast.Break):
    - self._break(node, current_klass)
    - elif isinstance(node, ast.Continue):
    - self._continue(node, current_klass)
    - elif isinstance(node, ast.Assign):
    - self._assign(node, current_klass)
    - elif isinstance(node, ast.AugAssign):
    - self._augassign(node, current_klass)
    - elif isinstance(node, ast.Discard):
    - self._discard(node, current_klass)
    - elif isinstance(node, ast.If):
    - self._if(node, current_klass)
    - elif isinstance(node, ast.For):
    - self._for(node, current_klass)
    - elif isinstance(node, ast.While):
    - self._while(node, current_klass)
    - elif isinstance(node, ast.Subscript):
    - self._subscript_stmt(node, current_klass)
    - elif isinstance(node, ast.Global):
    - self._global(node, current_klass)
    - elif isinstance(node, ast.Pass):
    - pass
    - elif isinstance(node, ast.Function):
    - self._function(node, True)
    - elif isinstance(node, ast.Printnl):
    - self._print(node, current_klass)
    - elif isinstance(node, ast.Print):
    - self._print(node, current_klass)
    - elif isinstance(node, ast.TryExcept):
    - self._tryExcept(node, current_klass)
    - elif isinstance(node, ast.Raise):
    - self._raise(node, current_klass)
    - else:
    - raise TranslationError("unsupported type (in _stmt)", node)
    -
    - if debugStmt:
    -
    - lt = self.get_line_trace(node)
    -
    - haltException = self.module_prefix + "HaltException"
    - isHaltFunction = self.module_prefix + "IsHaltException"
    -
    - print >>self.output, ' } catch (__err) {'
    - print >>self.output, ' if (' + isHaltFunction + '(__err.name)) {'
    - print >>self.output, ' throw __err;'
    - print >>self.output, ' } else {'
    - print >>self.output, " st = sys.printstack() + "\
    - + '"%s"' % lt + "+ '\\n' ;"
    - print >>self.output, ' alert("' + "Error in " \
    - + lt + '"' \
    - + '+"\\n"+__err.name+": "+__err.message'\
    - + '+"\\n\\nStack trace:\\n"' \
    - + '+st' \
    - + ');'
    - print >>self.output, ' debugger;'
    -
    - print >>self.output, ' throw new ' + self.module_prefix + "HaltException();"
    - print >>self.output, ' }'
    - print >>self.output, ' }'
    -
    -
    - def get_line_trace(self, node):
    - lineNum = "Unknown"
    - srcLine = ""
    - if hasattr(node, "lineno"):
    - if node.lineno != None:
    - lineNum = node.lineno
    - srcLine = self.src[min(lineNum, len(self.src))-1]
    - srcLine = srcLine.replace('\\', '\\\\')
    - srcLine = srcLine.replace('"', '\\"')
    - srcLine = srcLine.replace("'", "\\'")
    -
    - return self.raw_module_name + ".py, line " \
    - + str(lineNum) + ":"\
    - + "\\n" \
    - + " " + srcLine
    -
    - def _augassign(self, node, current_klass):
    - v = node.node
    - if isinstance(v, ast.Getattr):
    - # XXX HACK! don't allow += on return result of getattr.
    - # TODO: create a temporary variable or something.
    - lhs = self._getattr(v, current_klass, False)
    - else:
    - lhs = self._name(node.node, current_klass)
    - op = node.op
    - rhs = self.expr(node.expr, current_klass)
    - print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
    -
    -
    - def _assign(self, node, current_klass, top_level = False):
    - if len(node.nodes) != 1:
    - tempvar = '__temp'+str(node.lineno)
    - tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno)
    - self._assign(tnode, current_klass, top_level)
    - for v in node.nodes:
    - tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno)
    - self._assign(tnode2, current_klass, top_level)
    - return
    -
    - local_var_names = None
    - if len(self.local_arg_stack) > 0:
    - local_var_names = self.local_arg_stack[-1]
    -
    - def _lhsFromAttr(v, current_klass):
    - attr_name = v.attrname
    - if isinstance(v.expr, ast.Name):
    - obj = v.expr.name
    - lhs = self._name(v.expr, current_klass) + "." + attr_name
    - elif isinstance(v.expr, ast.Getattr):
    - lhs = self._getattr(v, current_klass)
    - elif isinstance(v.expr, ast.Subscript):
    - lhs = self._subscript(v.expr, current_klass) + "." + attr_name
    - else:
    - raise TranslationError("unsupported type (in _assign)", v.expr)
    - return lhs
    -
    - def _lhsFromName(v, top_level, current_klass):
    - if top_level:
    - if current_klass:
    - lhs = UU+current_klass.name_ + ".prototype.__class__." \
    - + v.name
    - else:
    - self.top_level_vars.add(v.name)
    - vname = self.modpfx() + v.name
    - if not self.modpfx() and v.name not in\
    - self.method_imported_globals:
    - lhs = "var " + vname
    - else:
    - lhs = UU + vname
    - self.add_local_arg(v.name)
    - else:
    - if v.name in local_var_names:
    - lhs = v.name
    - elif v.name in self.method_imported_globals:
    - lhs = self.modpfx() + v.name
    - else:
    - lhs = "var " + v.name
    - self.add_local_arg(v.name)
    - return lhs
    -
    - dbg = 0
    - v = node.nodes[0]
    - if isinstance(v, ast.AssAttr):
    - lhs = _lhsFromAttr(v, current_klass)
    - if v.flags == "OP_ASSIGN":
    - op = "="
    - else:
    - raise TranslationError("unsupported flag (in _assign)", v)
    -
    - elif isinstance(v, ast.AssName):
    - lhs = _lhsFromName(v, top_level, current_klass)
    - if v.flags == "OP_ASSIGN":
    - op = "="
    - else:
    - raise TranslationError("unsupported flag (in _assign)", v)
    - elif isinstance(v, ast.Subscript):
    - if v.flags == "OP_ASSIGN":
    - obj = self.expr(v.expr, current_klass)
    - if len(v.subs) != 1:
    - raise TranslationError("must have one sub (in _assign)", v)
    - idx = self.expr(v.subs[0], current_klass)
    - value = self.expr(node.expr, current_klass)
    - print >>self.output, " " + obj + ".__setitem__(" + idx + ", " + value + ");"
    - return
    - else:
    - raise TranslationError("unsupported flag (in _assign)", v)
    - elif isinstance(v, (ast.AssList, ast.AssTuple)):
    - uniqueID = self.nextTupleAssignID
    - self.nextTupleAssignID += 1
    - tempName = "__tupleassign" + str(uniqueID) + "__"
    - print >>self.output, " var " + tempName + " = " + \
    - self.expr(node.expr, current_klass) + ";"
    - for index,child in enumerate(v.getChildNodes()):
    - rhs = tempName + ".__getitem__(" + str(index) + ")"
    -
    - if isinstance(child, ast.AssAttr):
    - lhs = _lhsFromAttr(child, current_klass)
    - elif isinstance(child, ast.AssName):
    - lhs = _lhsFromName(child, top_level, current_klass)
    - elif isinstance(child, ast.Subscript):
    - if child.flags == "OP_ASSIGN":
    - obj = self.expr(child.expr, current_klass)
    - if len(child.subs) != 1:
    - raise TranslationError("must have one sub " +
    - "(in _assign)", child)
    - idx = self.expr(child.subs[0], current_klass)
    - value = self.expr(node.expr, current_klass)
    - print >>self.output, " " + obj + ".__setitem__(" \
    - + idx + ", " + rhs + ");"
    - continue
    - print >>self.output, " " + lhs + " = " + rhs + ";"
    - return
    - else:
    - raise TranslationError("unsupported type (in _assign)", v)
    -
    - rhs = self.expr(node.expr, current_klass)
    - if dbg:
    - print "b", repr(node.expr), rhs
    - print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
    -
    -
    - def _discard(self, node, current_klass):
    -
    - if isinstance(node.expr, ast.CallFunc):
    - debugStmt = self.debug and not self._isNativeFunc(node)
    - if debugStmt and isinstance(node.expr.node, ast.Name) and \
    - node.expr.node.name == 'import_wait':
    - debugStmt = False
    - if debugStmt:
    - st = self.get_line_trace(node)
    - print >>self.output, "sys.addstack('%s');\n" % st
    - if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME:
    - if len(node.expr.args) != 1:
    - raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr)
    - if not isinstance(node.expr.args[0], ast.Const):
    - raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr)
    - raw_js = node.expr.args[0].value
    - print >>self.output, raw_js
    - else:
    - expr = self._callfunc(node.expr, current_klass)
    - print >>self.output, " " + expr + ";"
    -
    - if debugStmt:
    - print >>self.output, "sys.popstack();\n"
    -
    - elif isinstance(node.expr, ast.Const):
    - if node.expr.value is not None: # Empty statements generate ignore None
    - print >>self.output, self._const(node.expr)
    - else:
    - raise TranslationError("unsupported type (in _discard)", node.expr)
    -
    -
    - def _if(self, node, current_klass):
    - for i in range(len(node.tests)):
    - test, consequence = node.tests[i]
    - if i == 0:
    - keyword = "if"
    - else:
    - keyword = "else if"
    -
    - self._if_test(keyword, test, consequence, current_klass)
    -
    - if node.else_:
    - keyword = "else"
    - test = None
    - consequence = node.else_
    -
    - self._if_test(keyword, test, consequence, current_klass)
    -
    -
    - def _if_test(self, keyword, test, consequence, current_klass):
    - if test:
    - expr = self.expr(test, current_klass)
    -
    - print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {"
    - else:
    - print >>self.output, " " + keyword + " {"
    -
    - if isinstance(consequence, ast.Stmt):
    - for child in consequence.nodes:
    - self._stmt(child, current_klass)
    - else:
    - raise TranslationError("unsupported type (in _if_test)", consequence)
    -
    - print >>self.output, " }"
    -
    -
    - def _from(self, node):
    - for name in node.names:
    - # look up "hack" in AppTranslator as to how findFile gets here
    - module_name = node.modname + "." + name[0]
    - try:
    - ff = self.findFile(module_name + ".py")
    - except Exception:
    - ff = None
    - if ff:
    - self.add_imported_module(module_name)
    - else:
    - self.imported_classes[name[0]] = node.modname
    -
    -
    - def _compare(self, node, current_klass):
    - lhs = self.expr(node.expr, current_klass)
    -
    - if len(node.ops) != 1:
    - raise TranslationError("only one ops supported (in _compare)", node)
    -
    - op = node.ops[0][0]
    - rhs_node = node.ops[0][1]
    - rhs = self.expr(rhs_node, current_klass)
    -
    - if op == "==":
    - return "pyjslib.eq(%s, %s)" % (lhs, rhs)
    - if op == "in":
    - return rhs + ".__contains__(" + lhs + ")"
    - elif op == "not in":
    - return "!" + rhs + ".__contains__(" + lhs + ")"
    - elif op == "is":
    - op = "==="
    - elif op == "is not":
    - op = "!=="
    -
    - return "(" + lhs + " " + op + " " + rhs + ")"
    -
    -
    - def _not(self, node, current_klass):
    - expr = self.expr(node.expr, current_klass)
    -
    - return "!(" + expr + ")"
    -
    - def _or(self, node, current_klass):
    - expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')'
    - return expr
    -
    - def _and(self, node, current_klass):
    - expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")"
    - return expr
    -
    - def _for(self, node, current_klass):
    - assign_name = ""
    - assign_tuple = ""
    -
    - # based on Bob Ippolito's Iteration in Javascript code
    - if isinstance(node.assign, ast.AssName):
    - assign_name = node.assign.name
    - self.add_local_arg(assign_name)
    - if node.assign.flags == "OP_ASSIGN":
    - op = "="
    - elif isinstance(node.assign, ast.AssTuple):
    - op = "="
    - i = 0
    - for child in node.assign:
    - child_name = child.name
    - if assign_name == "":
    - assign_name = "temp_" + child_name
    - self.add_local_arg(child_name)
    - assign_tuple += """
    - var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i);
    - """ % locals()
    - i += 1
    - else:
    - raise TranslationError("unsupported type (in _for)", node.assign)
    -
    - if isinstance(node.list, ast.Name):
    - list_expr = self._name(node.list, current_klass)
    - elif isinstance(node.list, ast.Getattr):
    - list_expr = self._getattr(node.list, current_klass)
    - elif isinstance(node.list, ast.CallFunc):
    - list_expr = self._callfunc(node.list, current_klass)
    - else:
    - raise TranslationError("unsupported type (in _for)", node.list)
    -
    - lhs = "var " + assign_name
    - iterator_name = "__" + assign_name
    -
    - print >>self.output, """
    - var %(iterator_name)s = %(list_expr)s.__iter__();
    - try {
    - while (true) {
    - %(lhs)s %(op)s %(iterator_name)s.next();
    - %(assign_tuple)s
    - """ % locals()
    - for node in node.body.nodes:
    - self._stmt(node, current_klass)
    - print >>self.output, """
    - }
    - } catch (e) {
    - if (e.__name__ != pyjslib.StopIteration.__name__) {
    - throw e;
    - }
    - }
    - """ % locals()
    -
    -
    - def _while(self, node, current_klass):
    - test = self.expr(node.test, current_klass)
    - print >>self.output, " while (pyjslib.bool(" + test + ")) {"
    - if isinstance(node.body, ast.Stmt):
    - for child in node.body.nodes:
    - self._stmt(child, current_klass)
    - else:
    - raise TranslationError("unsupported type (in _while)", node.body)
    - print >>self.output, " }"
    -
    -
    - def _const(self, node):
    - if isinstance(node.value, int):
    - return str(node.value)
    - elif isinstance(node.value, float):
    - return str(node.value)
    - elif isinstance(node.value, basestring):
    - v = node.value
    - if isinstance(node.value, unicode):
    - v = v.encode('utf-8')
    - return "String('%s')" % escapejs(v)
    - elif node.value is None:
    - return "null"
    - else:
    - raise TranslationError("unsupported type (in _const)", node)
    -
    - def _unaryadd(self, node, current_klass):
    - return self.expr(node.expr, current_klass)
    -
    - def _unarysub(self, node, current_klass):
    - return "-" + self.expr(node.expr, current_klass)
    -
    - def _add(self, node, current_klass):
    - return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass)
    -
    - def _sub(self, node, current_klass):
    - return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass)
    -
    - def _div(self, node, current_klass):
    - return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass)
    -
    - def _mul(self, node, current_klass):
    - return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass)
    -
    - def _mod(self, node, current_klass):
    - if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType):
    - self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used
    - return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")"
    - return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass)
    -
    - def _invert(self, node, current_klass):
    - return "~" + self.expr(node.expr, current_klass)
    -
    - def _bitand(self, node, current_klass):
    - return " & ".join([self.expr(child, current_klass) for child in node.nodes])
    -
    - def _bitshiftleft(self, node, current_klass):
    - return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass)
    -
    - def _bitshiftright(self, node, current_klass):
    - return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass)
    -
    - def _bitxor(self,node, current_klass):
    - return " ^ ".join([self.expr(child, current_klass) for child in node.nodes])
    -
    - def _bitor(self, node, current_klass):
    - return " | ".join([self.expr(child, current_klass) for child in node.nodes])
    -
    - def _subscript(self, node, current_klass):
    - if node.flags == "OP_APPLY":
    - if len(node.subs) == 1:
    - return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")"
    - else:
    - raise TranslationError("must have one sub (in _subscript)", node)
    - else:
    - raise TranslationError("unsupported flag (in _subscript)", node)
    -
    - def _subscript_stmt(self, node, current_klass):
    - if node.flags == "OP_DELETE":
    - print >>self.output, " " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");"
    - else:
    - raise TranslationError("unsupported flag (in _subscript)", node)
    -
    - def _list(self, node, current_klass):
    - return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
    -
    - def _dict(self, node, current_klass):
    - items = []
    - for x in node.items:
    - key = self.expr(x[0], current_klass)
    - value = self.expr(x[1], current_klass)
    - items.append("[" + key + ", " + value + "]")
    - return "new pyjslib.Dict([" + ", ".join(items) + "])"
    -
    - def _tuple(self, node, current_klass):
    - return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
    -
    - def _lambda(self, node, current_klass):
    - if node.varargs:
    - raise TranslationError("varargs are not supported in Lambdas", node)
    - if node.kwargs:
    - raise TranslationError("kwargs are not supported in Lambdas", node)
    - res = cStringIO.StringIO()
    - arg_names = list(node.argnames)
    - function_args = ", ".join(arg_names)
    - for child in node.getChildNodes():
    - expr = self.expr(child, None)
    - print >> res, "function (%s){" % function_args
    - self._default_args_handler(node, arg_names, None,
    - output=res)
    - print >> res, 'return %s;}' % expr
    - return res.getvalue()
    -
    - def _slice(self, node, current_klass):
    - if node.flags == "OP_APPLY":
    - lower = "null"
    - upper = "null"
    - if node.lower != None:
    - lower = self.expr(node.lower, current_klass)
    - if node.upper != None:
    - upper = self.expr(node.upper, current_klass)
    - return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")"
    - else:
    - raise TranslationError("unsupported flag (in _slice)", node)
    -
    - def _global(self, node, current_klass):
    - for name in node.names:
    - self.method_imported_globals.add(name)
    -
    - def expr(self, node, current_klass):
    - if isinstance(node, ast.Const):
    - return self._const(node)
    - # @@@ not sure if the parentheses should be here or in individual operator functions - JKT
    - elif isinstance(node, ast.Mul):
    - return " ( " + self._mul(node, current_klass) + " ) "
    - elif isinstance(node, ast.Add):
    - return " ( " + self._add(node, current_klass) + " ) "
    - elif isinstance(node, ast.Sub):
    - return " ( " + self._sub(node, current_klass) + " ) "
    - elif isinstance(node, ast.Div):
    - return " ( " + self._div(node, current_klass) + " ) "
    - elif isinstance(node, ast.Mod):
    - return self._mod(node, current_klass)
    - elif isinstance(node, ast.UnaryAdd):
    - return self._unaryadd(node, current_klass)
    - elif isinstance(node, ast.UnarySub):
    - return self._unarysub(node, current_klass)
    - elif isinstance(node, ast.Not):
    - return self._not(node, current_klass)
    - elif isinstance(node, ast.Or):
    - return self._or(node, current_klass)
    - elif isinstance(node, ast.And):
    - return self._and(node, current_klass)
    - elif isinstance(node, ast.Invert):
    - return self._invert(node, current_klass)
    - elif isinstance(node, ast.Bitand):
    - return "("+self._bitand(node, current_klass)+")"
    - elif isinstance(node,ast.LeftShift):
    - return self._bitshiftleft(node, current_klass)
    - elif isinstance(node, ast.RightShift):
    - return self._bitshiftright(node, current_klass)
    - elif isinstance(node, ast.Bitxor):
    - return "("+self._bitxor(node, current_klass)+")"
    - elif isinstance(node, ast.Bitor):
    - return "("+self._bitor(node, current_klass)+")"
    - elif isinstance(node, ast.Compare):
    - return self._compare(node, current_klass)
    - elif isinstance(node, ast.CallFunc):
    - return self._callfunc(node, current_klass)
    - elif isinstance(node, ast.Name):
    - return self._name(node, current_klass)
    - elif isinstance(node, ast.Subscript):
    - return self._subscript(node, current_klass)
    - elif isinstance(node, ast.Getattr):
    - return self._getattr(node, current_klass)
    - elif isinstance(node, ast.List):
    - return self._list(node, current_klass)
    - elif isinstance(node, ast.Dict):
    - return self._dict(node, current_klass)
    - elif isinstance(node, ast.Tuple):
    - return self._tuple(node, current_klass)
    - elif isinstance(node, ast.Slice):
    - return self._slice(node, current_klass)
    - elif isinstance(node, ast.Lambda):
    - return self._lambda(node, current_klass)
    - else:
    - raise TranslationError("unsupported type (in expr)", node)
    -
    -
    -
    -import cStringIO
    -
    -def translate(file_name, module_name, debug=False):
    - f = file(file_name, "r")
    - src = f.read()
    - f.close()
    - output = cStringIO.StringIO()
    - mod = compiler.parseFile(file_name)
    - t = Translator(module_name, module_name, module_name, src, debug, mod, output)
    - return output.getvalue()
    -
    -
    -class PlatformParser:
    - def __init__(self, platform_dir = "", verbose=True):
    - self.platform_dir = platform_dir
    - self.parse_cache = {}
    - self.platform = ""
    - self.verbose = verbose
    -
    - def setPlatform(self, platform):
    - self.platform = platform
    -
    - def parseModule(self, module_name, file_name):
    -
    - importing = False
    - if not self.parse_cache.has_key(file_name):
    - importing = True
    - mod = compiler.parseFile(file_name)
    - self.parse_cache[file_name] = mod
    - else:
    - mod = self.parse_cache[file_name]
    -
    - override = False
    - platform_file_name = self.generatePlatformFilename(file_name)
    - if self.platform and os.path.isfile(platform_file_name):
    - mod = copy.deepcopy(mod)
    - mod_override = compiler.parseFile(platform_file_name)
    - self.merge(mod, mod_override)
    - override = True
    -
    - if self.verbose:
    - if override:
    - print "Importing %s (Platform %s)" % (module_name, self.platform)
    - elif importing:
    - print "Importing %s" % (module_name)
    -
    - return mod, override
    -
    - def generatePlatformFilename(self, file_name):
    - (module_name, extension) = os.path.splitext(os.path.basename(file_name))
    - platform_file_name = module_name + self.platform + extension
    -
    - return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name)
    -
    - def merge(self, tree1, tree2):
    - for child in tree2.node:
    - if isinstance(child, ast.Function):
    - self.replaceFunction(tree1, child.name, child)
    - elif isinstance(child, ast.Class):
    - self.replaceClassMethods(tree1, child.name, child)
    -
    - return tree1
    -
    - def replaceFunction(self, tree, function_name, function_node):
    - # find function to replace
    - for child in tree.node:
    - if isinstance(child, ast.Function) and child.name == function_name:
    - self.copyFunction(child, function_node)
    - return
    - raise TranslationError("function not found: " + function_name, function_node)
    -
    - def replaceClassMethods(self, tree, class_name, class_node):
    - # find class to replace
    - old_class_node = None
    - for child in tree.node:
    - if isinstance(child, ast.Class) and child.name == class_name:
    - old_class_node = child
    - break
    -
    - if not old_class_node:
    - raise TranslationError("class not found: " + class_name, class_node)
    -
    - # replace methods
    - for function_node in class_node.code:
    - if isinstance(function_node, ast.Function):
    - found = False
    - for child in old_class_node.code:
    - if isinstance(child, ast.Function) and child.name == function_node.name:
    - found = True
    - self.copyFunction(child, function_node)
    - break
    -
    - if not found:
    - raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node)
    -
    - def copyFunction(self, target, source):
    - target.code = source.code
    - target.argnames = source.argnames
    - target.defaults = source.defaults
    - target.doc = source.doc # @@@ not sure we need to do this any more
    -
    -def dotreplace(fname):
    - path, ext = os.path.splitext(fname)
    - return path.replace(".", "/") + ext
    -
    -class AppTranslator:
    -
    - def __init__(self, library_dirs=[], parser=None, dynamic=False,
    - optimize=False, verbose=True):
    - self.extension = ".py"
    - self.optimize = optimize
    - self.library_modules = []
    - self.overrides = {}
    - self.library_dirs = path + library_dirs
    - self.dynamic = dynamic
    - self.verbose = verbose
    -
    - if not parser:
    - self.parser = PlatformParser()
    - else:
    - self.parser = parser
    -
    - self.parser.dynamic = dynamic
    -
    - def findFile(self, file_name):
    - if os.path.isfile(file_name):
    - return file_name
    -
    - for library_dir in self.library_dirs:
    - file_name = dotreplace(file_name)
    - full_file_name = os.path.join(
    - os.path.abspath(os.path.dirname(__file__)), library_dir, file_name)
    - if os.path.isfile(full_file_name):
    - return full_file_name
    -
    - fnameinit, ext = os.path.splitext(file_name)
    - fnameinit = fnameinit + "/__init__.py"
    -
    - full_file_name = os.path.join(
    - os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit)
    - if os.path.isfile(full_file_name):
    - return full_file_name
    -
    - raise Exception("file not found: " + file_name)
    -
    - def _translate(self, module_name, is_app=True, debug=False,
    - imported_js=set()):
    - if module_name not in self.library_modules:
    - self.library_modules.append(module_name)
    -
    - file_name = self.findFile(module_name + self.extension)
    -
    - output = cStringIO.StringIO()
    -
    - f = file(file_name, "r")
    - src = f.read()
    - f.close()
    -
    - mod, override = self.parser.parseModule(module_name, file_name)
    - if override:
    - override_name = "%s.%s" % (self.parser.platform.lower(),
    - module_name)
    - self.overrides[override_name] = override_name
    - if is_app:
    - mn = '__main__'
    - else:
    - mn = module_name
    - t = Translator(mn, module_name, module_name,
    - src, debug, mod, output, self.dynamic, self.optimize,
    - self.findFile)
    -
    - module_str = output.getvalue()
    - imported_js.update(set(t.imported_js))
    - imported_modules_str = ""
    - for module in t.imported_modules:
    - if module not in self.library_modules:
    - self.library_modules.append(module)
    - #imported_js.update(set(t.imported_js))
    - #imported_modules_str += self._translate(
    - # module, False, debug=debug, imported_js=imported_js)
    -
    - return imported_modules_str + module_str
    -
    -
    - def translate(self, module_name, is_app=True, debug=False,
    - library_modules=[]):
    - app_code = cStringIO.StringIO()
    - lib_code = cStringIO.StringIO()
    - imported_js = set()
    - self.library_modules = []
    - self.overrides = {}
    - for library in library_modules:
    - if library.endswith(".js"):
    - imported_js.add(library)
    - continue
    - self.library_modules.append(library)
    - if self.verbose:
    - print 'Including LIB', library
    - print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n'
    - print >> lib_code, self._translate(
    - library, False, debug=debug, imported_js=imported_js)
    -
    - print >> lib_code, "/* initialize static library */"
    - print >> lib_code, "%s%s();\n" % (UU, library)
    -
    - print >> lib_code, '\n//\n// END LIB '+library+'\n//\n'
    - if module_name:
    - print >> app_code, self._translate(
    - module_name, is_app, debug=debug, imported_js=imported_js)
    - for js in imported_js:
    - path = self.findFile(js)
    - if os.path.isfile(path):
    - if self.verbose:
    - print 'Including JS', js
    - print >> lib_code, '\n//\n// BEGIN JS '+js+'\n//\n'
    - print >> lib_code, file(path).read()
    - print >> lib_code, '\n//\n// END JS '+js+'\n//\n'
    - else:
    - print >>sys.stderr, 'Warning: Unable to find imported javascript:', js
    - return lib_code.getvalue(), app_code.getvalue()
    -
    -usage = """
    - usage: %s file_name [module_name]
    -"""
    -
    -def main():
    - import sys
    - if len(sys.argv)<2:
    - print >> sys.stderr, usage % sys.argv[0]
    - sys.exit(1)
    - file_name = os.path.abspath(sys.argv[1])
    - if not os.path.isfile(file_name):
    - print >> sys.stderr, "File not found %s" % file_name
    - sys.exit(1)
    - if len(sys.argv) > 2:
    - module_name = sys.argv[2]
    - else:
    - module_name = None
    - print translate(file_name, module_name),
    -
    -if __name__ == "__main__":
    - main()
    -
    --- 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 @@
    -import wx
    -import os, sys, shutil
    -
    -from ConfigTree import opjimg
    -from confnodes.python import PythonCodeTemplate
    -
    -from pyjs import translate
    -
    -from docutils import *
    -
    -class RootClass:
    -
    - ConfNodeMethods = [
    - {"bitmap" : os.path.join("images","ImportSVG"),
    - "name" : _("Import SVG"),
    - "tooltip" : _("Import SVG"),
    - "method" : "_ImportSVG"},
    - {"bitmap" : os.path.join("images","ImportSVG"),
    - "name" : _("Inkscape"),
    - "tooltip" : _("Create HMI"),
    - "method" : "_StartInkscape"},
    - ]
    -
    - def ConfNodePath(self):
    - return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType)
    -
    - def _getSVGpath(self):
    - # define name for IEC raw code file
    - return os.path.join(self.CTNPath(), "gui.svg")
    -
    - def _getSVGUIserverpath(self):
    - return os.path.join(os.path.dirname(__file__), "svgui_server.py")
    -
    - def CTNGenerate_C(self, buildpath, locations):
    - """
    - Return C code generated by iec2c compiler
    - when _generate_softPLC have been called
    - @param locations: ignored
    - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    - """
    -
    - current_location = self.GetCurrentLocation()
    - # define a unique name for the generated C file
    - location_str = "_".join(map(lambda x:str(x), current_location))
    -
    - res = ([], "", False)
    -
    - svgfile=self._getSVGpath()
    - if os.path.exists(svgfile):
    - res += (("gui.svg", file(svgfile,"rb")),)
    -
    - svguiserverfile = open(self._getSVGUIserverpath(), 'r')
    - svguiservercode = svguiserverfile.read()
    - svguiserverfile.close()
    -
    - svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js")
    - svguilibfile = open(svguilibpath, 'w')
    - svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys"))
    - svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read())
    - svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib"))
    - svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib"))
    - svguilibfile.write("pyjslib();\nsvguilib();\n")
    - svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read())
    - svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read())
    - svguilibfile.close()
    - jsmodules = {"LiveSVGPage": "svguilib.js"}
    - res += (("svguilib.js", file(svguilibpath,"rb")),)
    -
    - runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
    - runtimefile = open(runtimefile_path, 'w')
    - runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"})
    - runtimefile.write("""
    -def _runtime_%(location)s_begin():
    - website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
    -
    -def _runtime_%(location)s_cleanup():
    - website.UnLoadHMI()
    -
    -""" % {"location": location_str,
    - "svgui_class": "SVGUI_HMI",
    - "jsmodules" : str(jsmodules),
    - })
    - runtimefile.close()
    -
    - res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),)
    -
    - return res
    -
    - def _ImportSVG(self):
    - dialog = wx.FileDialog(self.GetCTRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "", _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN)
    - if dialog.ShowModal() == wx.ID_OK:
    - svgpath = dialog.GetPath()
    - if os.path.isfile(svgpath):
    - shutil.copy(svgpath, self._getSVGpath())
    - else:
    - self.GetCTRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath)
    - dialog.Destroy()
    -
    - def _StartInkscape(self):
    - svgfile = self._getSVGpath()
    - open_inkscape = True
    - if not self.GetCTRoot().CheckProjectPathPerm():
    - dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
    - _("You don't have write permissions.\nOpen Inkscape anyway ?"),
    - _("Open Inkscape"),
    - wx.YES_NO|wx.ICON_QUESTION)
    - open_inkscape = dialog.ShowModal() == wx.ID_YES
    - dialog.Destroy()
    - if open_inkscape:
    - if not os.path.isfile(svgfile):
    - svgfile = None
    - open_svg(svgfile)
    --- 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 @@
    -#!/usr/bin/python
    -# -*- coding: utf-8 -*-
    -
    -import os
    -
    -from nevow import rend, appserver, inevow, tags, loaders, athena
    -import simplejson as json
    -
    -svgfile = '%(svgfile)s'
    -
    -svguiWidgets = {}
    -
    -currentId = 0
    -def getNewId():
    - global currentId
    - currentId += 1
    - return currentId
    -
    -class SvguiWidget:
    -
    - def __init__(self, classname, id, **kwargs):
    - self.classname = classname
    - self.id = id
    - self.attrs = kwargs.copy()
    - self.inputs = {}
    - self.outputs = {}
    - self.inhibit = False
    - self.changed = False
    -
    - def setinput(self, attrname, value):
    - self.inputs[attrname] = value
    -
    - def getinput(self, attrname, default=None):
    - if not self.inputs.has_key(attrname):
    - self.inputs[attrname] = default
    - return self.inputs[attrname]
    -
    - def setoutput(self, attrname, value):
    - if self.outputs.get(attrname) != value:
    - self.outputs[attrname] = value
    - self.changed = True
    - self.RefreshInterface()
    -
    - def updateoutputs(self, **kwargs):
    - for attrname, value in kwargs.iteritems():
    - if self.outputs.get(attrname) != value:
    - self.outputs[attrname] = value
    - self.changed = True
    - self.RefreshInterface()
    -
    - def RefreshInterface(self):
    - interface = website.getHMI()
    - if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit:
    - self.changed = False
    - d = interface.sendData(self)
    - if d is not None:
    - self.inhibit = True
    - d.addCallback(self.InterfaceRefreshed)
    -
    - def InterfaceRefreshed(self, result):
    - self.inhibit = False
    - if self.changed:
    - self.RefreshInterface()
    -
    -def get_object_init_state(obj):
    - # Convert objects to a dictionary of their representation
    - attrs = obj.attrs.copy()
    - attrs.update(obj.inputs)
    - d = { '__class__': obj.classname,
    - 'id': obj.id,
    - 'kwargs': json.dumps(attrs),
    - }
    - return d
    -
    -def get_object_current_state(obj):
    - # Convert objects to a dictionary of their representation
    - d = { '__class__': obj.classname,
    - 'id': obj.id,
    - 'kwargs': json.dumps(obj.outputs),
    - }
    - return d
    -
    -class SVGUI_HMI(website.PLCHMI):
    - jsClass = u"LiveSVGPage.LiveSVGWidget"
    -
    - docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[
    - tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))),
    - ])
    -
    - def HMIinitialisation(self):
    - gadgets = []
    - for gadget in svguiWidgets.values():
    - gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
    - d = self.callRemote('init', gadgets)
    - d.addCallback(self.HMIinitialised)
    -
    - def sendData(self,data):
    - if self.initialised:
    - return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
    - return None
    -
    - def setattr(self, id, attrname, value):
    - svguiWidgets[id].setinput(attrname, value)
    -
    -def createSVGUIControl(*args, **kwargs):
    - id = getNewId()
    - gad = SvguiWidget(args[0], id, **kwargs)
    - svguiWidgets[id] = gad
    - gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
    - interface = website.getHMI()
    - if isinstance(interface, SVGUI_HMI) and interface.initialised:
    - interface.callRemote('init', gadget)
    - return id
    -
    -def setAttr(id, attrname, value):
    - gad = svguiWidgets.get(id, None)
    - if gad is not None:
    - gad.setoutput(attrname, value)
    -
    -def updateAttr(id, **kwargs):
    - gad = svguiWidgets.get(id, None)
    - if gad is not None:
    - gad.updateoutput(**kwargs)
    -
    -def getAttr(id, attrname, default=None):
    - gad = svguiWidgets.get(id, None)
    - if gad is not None:
    - return gad.getinput(attrname, default)
    - return default
    -
    --- 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 @@
    -
    -class button:
    -
    - def __init__(self, parent, id, args):
    - self.parent = parent
    - self.id = id
    - self.back_elt = getSVGElementById(args.back_id)
    - self.sele_elt = getSVGElementById(args.sele_id)
    - self.toggle = args.toggle
    - self.active = args.active
    - if args.state != undefined:
    - self.state = args.state
    - else:
    - self.state = False
    - self.dragging = False
    - if self.toggle:
    - self.up = not self.state
    - else:
    - self.up = True
    -
    - # Add event on each element of the button
    - if self.active:
    - self.back_elt.addEventListener("mouseup", self, False)
    - self.back_elt.addEventListener("mousedown", self, False)
    - self.back_elt.addEventListener("mouseover", self, False)
    - self.back_elt.addEventListener("mouseout", self, False)
    -
    - self.sele_elt.addEventListener("mouseup", self, False)
    - self.sele_elt.addEventListener("mousedown", self, False)
    - self.sele_elt.addEventListener("mouseover", self, False)
    - self.sele_elt.addEventListener("mouseout", self, False)
    -
    - blockSVGElementDrag(self.back_elt)
    - blockSVGElementDrag(self.sele_elt)
    -
    - self.updateElements()
    -
    - # method to display the current state of interface
    - def updateElements(self):
    - if self.up:
    - self.sele_elt.setAttribute("display", "none")
    - self.back_elt.removeAttribute("display")
    - else:
    - self.sele_elt.removeAttribute("display")
    - self.back_elt.setAttribute("display", "none")
    -
    - def updateValues(self, values):
    - if values.state != self.state:
    - self.state = values.state
    - self.up = not self.state
    - updateAttr(self.id, 'state', self.state)
    - self.updateElements()
    -
    - def handleEvent(self, evt):
    - # Quand le bouton de la souris est presse
    - if evt.type == "mousedown":
    - evt.stopPropagation()
    - setCurrentObject(self)
    -
    - self.dragging = True
    -
    - if self.toggle:
    - self.up = self.state
    - else:
    - self.up = False
    - self.state = True
    - updateAttr(self.id, 'state', self.state)
    - self.updateElements()
    -
    - if isCurrentObject(self) and self.dragging:
    - # Quand le bouton est survole
    - if evt.type == "mouseover" and self.toggle:
    - self.up = self.state
    - self.updateElements()
    -
    - # Quand le curseur quitte la zone du bouton
    - elif evt.type == "mouseout" and self.toggle:
    - self.up = not self.state
    - self.updateElements()
    -
    - # Quand le bouton de la souris est relache
    - elif evt.type == "mouseup":
    - evt.stopPropagation()
    - if self.toggle and self.up == self.state:
    - self.state = not self.state
    - updateAttr(self.id, 'state', self.state)
    - elif not self.toggle:
    - self.up = True
    - self.state = False
    - updateAttr(self.id, 'state', self.state)
    - self.updateElements()
    - self.dragging = False
    -
    -class textControl:
    -
    - def __init__(self, parent, id, args):
    - self.parent = parent
    - self.id = id
    - self.back_elt = getSVGElementById(args.back_id)
    - if args.text != undefined:
    - self.text = args.text
    - else:
    - self.text = ""
    - self.updateElements()
    -
    - def updateValues(self, values):
    - if values.text != self.value:
    - self.text = values.text
    - updateAttr(self.id, 'text', self.text)
    - self.updateElements()
    -
    - def updateElements(self):
    - self.back_elt.firstChild.firstChild.textContent = self.text
    -
    - def handleEvent(self, evt):
    - pass
    -
    \ No newline at end of file
    --- 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 @@
    -WxGlade HMI
    \ 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 @@
    -import wx
    -import os, sys
    -from xml.dom import minidom
    -
    -from ConfigTree import opjimg
    -from confnodes.python import PythonCodeTemplate
    -
    -class RootClass(PythonCodeTemplate):
    -
    - ConfNodeMethods = [
    - {"bitmap" : opjimg("editWXGLADE"),
    - "name" : _("WXGLADE GUI"),
    - "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
    - "method" : "_editWXGLADE"},
    - ]
    -
    - def _getWXGLADEpath(self):
    - # define name for IEC raw code file
    - return os.path.join(self.CTNPath(), "hmi.wxg")
    -
    - def launch_wxglade(self, options, wait=False):
    - from wxglade import __file__ as fileName
    - path = os.path.dirname(fileName)
    - glade = os.path.join(path, 'wxglade.py')
    - if wx.Platform == '__WXMSW__':
    - glade = "\"%s\""%glade
    - mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait]
    - os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options)
    -
    -
    - def CTNGenerate_C(self, buildpath, locations):
    - """
    - Return C code generated by iec2c compiler
    - when _generate_softPLC have been called
    - @param locations: ignored
    - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    - """
    -
    - current_location = self.GetCurrentLocation()
    - # define a unique name for the generated C file
    - location_str = "_".join(map(lambda x:str(x), current_location))
    -
    - runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
    - runtimefile = open(runtimefile_path, 'w')
    -
    - hmi_frames = {}
    -
    - wxgfile_path=self._getWXGLADEpath()
    - if os.path.exists(wxgfile_path):
    - wxgfile = open(wxgfile_path, 'r')
    - wxgtree = minidom.parse(wxgfile)
    - wxgfile.close()
    -
    - for node in wxgtree.childNodes[1].childNodes:
    - if node.nodeType == wxgtree.ELEMENT_NODE:
    - hmi_frames[node._attrs["name"].value] = node._attrs["class"].value
    -
    - hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py")
    - if wx.Platform == '__WXMSW__':
    - wxgfile_path = "\"%s\""%wxgfile_path
    - wxghmipyfile_path = "\"%s\""%hmipyfile_path
    - else:
    - wxghmipyfile_path = hmipyfile_path
    - self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True)
    -
    - hmipyfile = open(hmipyfile_path, 'r')
    - runtimefile.write(hmipyfile.read())
    - hmipyfile.close()
    -
    - runtimefile.write(self.GetPythonCode())
    - runtimefile.write("""
    -%(declare)s
    -
    -def _runtime_%(location)s_begin():
    - global %(global)s
    -
    - def OnCloseFrame(evt):
    - wx.MessageBox(_("Please stop PLC to close"))
    -
    - %(init)s
    -
    -def _runtime_%(location)s_cleanup():
    - global %(global)s
    -
    - %(cleanup)s
    -
    -""" % {"location": location_str,
    - "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())),
    - "global": ",".join(hmi_frames.keys()),
    - "init": "\n".join(map(lambda x: """
    - %(name)s = %(class)s(None)
    - %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
    - %(name)s.Show()
    -""" % {"name": x[0], "class": x[1]},
    - hmi_frames.items())),
    - "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))})
    - runtimefile.close()
    -
    - return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
    -
    - def _editWXGLADE(self):
    - wxg_filename = self._getWXGLADEpath()
    - open_wxglade = True
    - if not self.GetCTRoot().CheckProjectPathPerm():
    - dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
    - _("You don't have write permissions.\nOpen wxGlade anyway ?"),
    - _("Open wxGlade"),
    - wx.YES_NO|wx.ICON_QUESTION)
    - open_wxglade = dialog.ShowModal() == wx.ID_YES
    - dialog.Destroy()
    - if open_wxglade:
    - if not os.path.exists(wxg_filename):
    - hmi_name = self.BaseParams.getName()
    - open(wxg_filename,"w").write("""<?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>
    - <title>frame_1</title>
    - </object>
    - </application>
    - """ % {"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
    - * flags.
    - *
    - * */
    -
    -#include "iec_types_all.h"
    -#include "POUS.h"
    -#include <string.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*/
    -static int PythonState;
    -#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);
    -void LockPython(void);
    -
    -int __init_%(location)s()
    -{
    - int i;
    - /* 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++)
    - EvalFBs[i] = NULL;
    - return 0;
    -}
    -
    -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_PLC :
    - 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();
    - }
    - UnLockPython();
    - }
    -}
    -/**
    - * 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){
    - /* mark as trigged */
    - __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);
    - /* Mark as free */
    - __SET_VAR(data__->, STATE, PYTHON_FB_FREE);
    - /* mark as not trigged */
    - if(!poll)
    - __SET_VAR(data__->, TRIGGED, 0);
    - /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
    - }else if(poll){
    - /* 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 */
    - if(!poll){
    - /* when not polling, a new answer imply reseting ack*/
    - __SET_VAR(data__->, ACK, 0);
    - }else{
    - /* when in polling, acting reset trigger */
    - __SET_VAR(data__->, TRIGGED, 0);
    - }
    - /* Mark FB busy */
    - __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);*/
    - /* Get a new line */
    - Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
    - }
    - }
    -}
    -
    -char* PythonIterator(char* result)
    -{
    - char* next_command;
    - PYTHON_EVAL* data__;
    - //printf("PythonIterator result %%s\n", result);
    - /*emergency exit*/
    - if(PythonState & PYTHON_FINISHED) return NULL;
    - /* take python mutex to prevent changing PLC data while PLC running */
    - LockPython();
    - /* Get current FB */
    - 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 */
    - if(result){
    - /* Get results len */
    - __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));
    - }else{
    - __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);
    - /* Get a new line */
    - 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)
    - {
    - UnLockPython();
    - /* wait next FB to eval */
    - //printf("PythonIterator wait\n");
    - if(WaitPythonCommands()) return NULL;
    - /*emergency exit*/
    - if(PythonState & PYTHON_FINISHED) return NULL;
    - LockPython();
    - }
    - /* 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 */
    - UnLockPython();
    - /* return the next command to eval */
    - return next_command;
    -}
    -
    --- 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"
    - productName="Beremiz"
    - productVersion="0.0"
    - creationDateTime="2008-12-14T16:53:26"/>
    - <contentHeader name="Beremiz non-standard POUs library"
    - modificationDateTime="2008-12-23T22:35:46">
    - <coordinateInfo>
    - <fbd>
    - <scaling x="0" y="0"/>
    - </fbd>
    - <ld>
    - <scaling x="0" y="0"/>
    - </ld>
    - <sfc>
    - <scaling x="0" y="0"/>
    - </sfc>
    - </coordinateInfo>
    - </contentHeader>
    - <types>
    - <dataTypes/>
    - <pous>
    - <pou name="python_eval" pouType="functionBlock">
    - <interface>
    - <inputVars>
    - <variable name="TRIG">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="CODE">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </inputVars>
    - <outputVars>
    - <variable name="ACK">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="RESULT">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </outputVars>
    - <localVars>
    - <variable name="STATE">
    - <type>
    - <DWORD/>
    - </type>
    - </variable>
    - <variable name="BUFFER">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="PREBUFFER">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="TRIGM1">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="TRIGGED">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - </localVars>
    - </interface>
    - <body>
    - <ST>
    -<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(0, data__);}]]>
    - </ST>
    - </body>
    - </pou>
    - <pou name="python_poll" pouType="functionBlock">
    - <interface>
    - <inputVars>
    - <variable name="TRIG">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="CODE">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </inputVars>
    - <outputVars>
    - <variable name="ACK">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="RESULT">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </outputVars>
    - <localVars>
    - <variable name="STATE">
    - <type>
    - <DWORD/>
    - </type>
    - </variable>
    - <variable name="BUFFER">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="PREBUFFER">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - <variable name="TRIGM1">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="TRIGGED">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - </localVars>
    - </interface>
    - <body>
    - <ST>
    -<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(1,(PYTHON_EVAL*)(void*)data__);}]]>
    - </ST>
    - </body>
    - </pou>
    - <pou name="python_gear" pouType="functionBlock">
    - <interface>
    - <inputVars>
    - <variable name="N">
    - <type>
    - <USINT/>
    - </type>
    - </variable>
    - <variable name="TRIG">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="CODE">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </inputVars>
    - <outputVars>
    - <variable name="ACK">
    - <type>
    - <BOOL/>
    - </type>
    - </variable>
    - <variable name="RESULT">
    - <type>
    - <string/>
    - </type>
    - </variable>
    - </outputVars>
    - <localVars>
    - <variable name="py_eval">
    - <type>
    - <derived name="python_eval"/>
    - </type>
    - </variable>
    - <variable name="COUNTER">
    - <type>
    - <USINT/>
    - </type>
    - </variable>
    - </localVars>
    - </interface>
    - <body>
    - <FBD>
    - <block localId="1" width="125" height="110" typeName="python_eval" instanceName="py_eval">
    - <position x="525" y="580"/>
    - <inputVariables>
    - <variable formalParameter="TRIG">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="CODE">
    - <connectionPointIn>
    - <relPosition x="0" y="85"/>
    - <connection refLocalId="4">
    - <position x="525" y="665"/>
    - <position x="370" y="665"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="ACK">
    - <connectionPointOut>
    - <relPosition x="125" y="40"/>
    - </connectionPointOut>
    - </variable>
    - <variable formalParameter="RESULT">
    - <connectionPointOut>
    - <relPosition x="125" y="85"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="2" height="35" width="25">
    - <position x="435" y="270"/>
    - <connectionPointOut>
    - <relPosition x="25" y="15"/>
    - </connectionPointOut>
    - <expression>N</expression>
    - </inVariable>
    - <inVariable localId="3" height="35" width="55">
    - <position x="275" y="585"/>
    - <connectionPointOut>
    - <relPosition x="55" y="15"/>
    - </connectionPointOut>
    - <expression>TRIG</expression>
    - </inVariable>
    - <inVariable localId="4" height="35" width="55">
    - <position x="315" y="650"/>
    - <connectionPointOut>
    - <relPosition x="55" y="15"/>
    - </connectionPointOut>
    - <expression>CODE</expression>
    - </inVariable>
    - <outVariable localId="5" height="35" width="45">
    - <position x="740" y="605"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="1" formalParameter="ACK">
    - <position x="740" y="620"/>
    - <position x="650" y="620"/>
    - </connection>
    - </connectionPointIn>
    - <expression>ACK</expression>
    - </outVariable>
    - <outVariable localId="6" height="35" width="75">
    - <position x="740" y="650"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="1" formalParameter="RESULT">
    - <position x="740" y="665"/>
    - <position x="650" y="665"/>
    - </connection>
    - </connectionPointIn>
    - <expression>RESULT</expression>
    - </outVariable>
    - <block localId="7" width="80" height="65" typeName="AND">
    - <position x="385" y="545"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="55"/>
    - <connection refLocalId="3">
    - <position x="385" y="600"/>
    - <position x="330" y="600"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="80" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="9" height="35" width="85">
    - <position x="240" y="330"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>COUNTER</expression>
    - </inVariable>
    - <block localId="10" width="80" height="65" typeName="ADD">
    - <position x="380" y="330"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <relPosition x="0" y="55"/>
    - <connection refLocalId="11">
    - <position x="380" y="385"/>
    - <position x="325" y="385"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="80" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="11" height="35" width="85">
    - <position x="240" y="370"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>USINT#1</expression>
    - </inVariable>
    - <block localId="13" width="80" height="65" typeName="EQ">
    - <position x="535" y="255"/>
    - <inputVariables>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="30"/>
    - <connection refLocalId="2">
    - <position x="535" y="285"/>
    - <position x="460" y="285"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN2">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="80" y="30"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <block localId="15" width="80" height="135" typeName="SEL">
    - <position x="785" y="245"/>
    - <inputVariables>
    - <variable formalParameter="G">
    - <connectionPointIn>
    - <relPosition x="0" y="40"/>
    - <connection refLocalId="13" formalParameter="OUT">
    - <position x="785" y="285"/>
    - <position x="615" y="285"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN0">
    - <connectionPointIn>
    - <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"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - <variable formalParameter="IN1">
    - <connectionPointIn>
    - <relPosition x="0" y="115"/>
    - <connection refLocalId="16">
    - <position x="785" y="360"/>
    - <position x="760" y="360"/>
    - </connection>
    - </connectionPointIn>
    - </variable>
    - </inputVariables>
    - <inOutVariables/>
    - <outputVariables>
    - <variable formalParameter="OUT">
    - <connectionPointOut>
    - <relPosition x="80" y="40"/>
    - </connectionPointOut>
    - </variable>
    - </outputVariables>
    - </block>
    - <inVariable localId="16" height="35" width="85">
    - <position x="675" y="345"/>
    - <connectionPointOut>
    - <relPosition x="85" y="15"/>
    - </connectionPointOut>
    - <expression>USINT#0</expression>
    - </inVariable>
    - <outVariable localId="17" height="35" width="85">
    - <position x="905" y="270"/>
    - <connectionPointIn>
    - <relPosition x="0" y="15"/>
    - <connection refLocalId="15" formalParameter="OUT">
    - <position x="905" y="285"/>
    - <position x="865" y="285"/>
    - </connection>
    - </connectionPointIn>
    - <expression>COUNTER</expression>
    - </outVariable>
    - </FBD>
    - </body>
    - </pou>
    - </pous>
    - </types>
    - <instances>
    - <configurations/>
    - </instances>
    -</project>
    --- 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 @@
    -import wx
    -import os
    -import modules
    -from ConfigTree import ConfigTreeNode, opjimg
    -from PLCControler import UndoBuffer
    -from PythonEditor import PythonEditor
    -
    -from xml.dom import minidom
    -from xmlclass import *
    -import cPickle
    -
    -PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd"))
    -
    -class PythonCodeTemplate:
    -
    - EditorType = PythonEditor
    -
    - def __init__(self):
    -
    - self.ConfNodeMethods.insert(0,
    - {"bitmap" : opjimg("editPYTHONcode"),
    - "name" : _("Edit Python File"),
    - "tooltip" : _("Edit Python File"),
    - "method" : "_OpenView"},
    - )
    -
    - filepath = self.PythonFileName()
    -
    - self.PythonCode = PythonClasses["Python"]()
    - if os.path.isfile(filepath):
    - xmlfile = open(filepath, 'r')
    - tree = minidom.parse(xmlfile)
    - xmlfile.close()
    -
    - for child in tree.childNodes:
    - if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
    - self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
    - self.CreatePythonBuffer(True)
    - else:
    - self.CreatePythonBuffer(False)
    - self.OnCTNSave()
    -
    - def ConfNodePath(self):
    - return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType)
    -
    - def PythonFileName(self):
    - return os.path.join(self.CTNPath(), "python.xml")
    -
    - def GetFilename(self):
    - if self.PythonBuffer.IsCurrentSaved():
    - return "python"
    - else:
    - return "~python~"
    -
    - def SetPythonCode(self, text):
    - self.PythonCode.settext(text)
    -
    - def GetPythonCode(self):
    - return self.PythonCode.gettext()
    -
    - def CTNTestModified(self):
    - return self.ChangesToSave or not self.PythonIsSaved()
    -
    - def OnCTNSave(self):
    - filepath = self.PythonFileName()
    -
    - text = "<?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"))
    - xmlfile.close()
    -
    - self.MarkPythonAsSaved()
    - return True
    -
    -#-------------------------------------------------------------------------------
    -# Current Buffering Management Functions
    -#-------------------------------------------------------------------------------
    -
    - """
    - Return a copy of the project
    - """
    - def Copy(self, model):
    - return cPickle.loads(cPickle.dumps(model))
    -
    - def CreatePythonBuffer(self, saved):
    - self.Buffering = False
    - self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
    -
    - def BufferPython(self):
    - self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
    -
    - def StartBuffering(self):
    - self.Buffering = True
    -
    - def EndBuffering(self):
    - if self.Buffering:
    - self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
    - self.Buffering = False
    -
    - def MarkPythonAsSaved(self):
    - self.EndBuffering()
    - self.PythonBuffer.CurrentSaved()
    -
    - def PythonIsSaved(self):
    - return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
    -
    - def LoadPrevious(self):
    - self.EndBuffering()
    - self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
    -
    - def LoadNext(self):
    - self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
    -
    - def GetBufferState(self):
    - first = self.PythonBuffer.IsFirst() and not self.Buffering
    - last = self.PythonBuffer.IsLast()
    - return not first, not last
    -
    -def _GetClassFunction(name):
    - def GetRootClass():
    - __import__("confnodes.python.modules." + name)
    - return getattr(modules, name).RootClass
    - return GetRootClass
    -
    -class RootClass(PythonCodeTemplate):
    -
    - # For root object, available Children Types are modules of the modules packages.
    - CTNChildrenTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
    -
    - def ConfNodePath(self):
    - return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType)
    -
    - def CTNGenerate_C(self, buildpath, locations):
    - """
    - Generate C code
    - @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    - @param locations: List of complete variables locations \
    - [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    - "NAME" : name of the variable (generally "__IW0_1_2" style)
    - "DIR" : direction "Q","I" or "M"
    - "SIZE" : size "X", "B", "W", "D", "L"
    - "LOC" : tuple of interger for IEC location (0,1,2,...)
    - }, ...]
    - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    - """
    - current_location = self.GetCurrentLocation()
    - # define a unique name for the generated C file
    - location_str = "_".join(map(lambda x:str(x), current_location))
    -
    - ctr = self.GetCTRoot()
    - ctr.GetIECProgramsAndVariables()
    -
    - 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))
    -
    - # prepare python code
    - 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)
    - pythonfile.close()
    -
    - runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
    - runtimefile = open(runtimefile_path, 'w')
    - runtimefile.write(self.GetPythonCode())
    - runtimefile.close()
    -
    - matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
    -
    - return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
    --- 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:complexType>
    - <xsd:annotation>
    - <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
    - </xsd:annotation>
    - <xsd:sequence>
    - <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
    - </xsd:sequence>
    - </xsd:complexType>
    - </xsd:element>
    -</xsd:schema>
    --- /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
    +
    +catalog = [
    + ('canfestival', _('CANopen support'), _('Map located variables over CANopen'), 'canfestival.canfestival.RootClass'),
    + ('c_ext', _('C extention'), _('Extend project with C code accessing located variables'), 'c_ext.c_ext.RootClass'),
    + ('py_ext', _('Python extention'), _('Extend project with Pyhon code executed asynchronously'), 'py_ext.py_ext.RootClass')]
    +
    --- /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 @@
    +import wx, wx.grid
    +import wx.stc as stc
    +import keyword
    +
    +from controls import EditorPanel
    +
    +if wx.Platform == '__WXMSW__':
    + faces = { 'times': 'Times New Roman',
    + 'mono' : 'Courier New',
    + 'helv' : 'Arial',
    + 'other': 'Comic Sans MS',
    + 'size' : 10,
    + 'size2': 8,
    + }
    +elif wx.Platform == '__WXMAC__':
    + faces = { 'times': 'Times New Roman',
    + 'mono' : 'Monaco',
    + 'helv' : 'Arial',
    + 'other': 'Comic Sans MS',
    + 'size' : 12,
    + 'size2': 10,
    + }
    +else:
    + faces = { 'times': 'Times',
    + 'mono' : 'Courier',
    + 'helv' : 'Helvetica',
    + 'other': 'new century schoolbook',
    + 'size' : 12,
    + 'size2': 10,
    + }
    +
    +[ID_PYTHONEDITOR,
    +] = [wx.NewId() for _init_ctrls in range(1)]
    +
    +def GetCursorPos(old, new):
    + old_length = len(old)
    + new_length = len(new)
    + common_length = min(old_length, new_length)
    + i = 0
    + for i in xrange(common_length):
    + if old[i] != new[i]:
    + break
    + if old_length < new_length:
    + if common_length > 0 and old[i] != new[i]:
    + return i + new_length - old_length
    + else:
    + 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]:
    + return i
    + else:
    + return i + 1
    + else:
    + return None
    +
    +class PythonEditor(EditorPanel):
    +
    + fold_symbols = 3
    +
    + 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)
    +
    + # Global default style
    + 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')
    + else:
    + 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')
    + # Highlighted brace
    + self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
    + # Unmatched brace
    + self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
    + # Indentation guide
    + self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
    +
    + # Python styles
    + self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
    + # Comments
    + self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
    + self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
    + # Numbers
    + 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')
    + # Keywords
    + self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
    + # Triple quotes
    + self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
    + self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
    + # Class names
    + self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
    + # Function names
    + self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
    + # Operators
    + 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')
    +
    + # Caret color
    + self.Editor.SetCaretForeground("BLUE")
    + # Selection background
    + 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!
    + # White space
    + 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
    + # edit them that way.
    + 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)))
    +
    + def __del__(self):
    + self.Controler.OnCloseEditor(self)
    +
    + def GetTitle(self):
    + fullname = self.Controler.CTNFullName()
    + if not self.Controler.PythonIsSaved():
    + return "~%s~" % fullname
    + return fullname
    +
    + def GetBufferState(self):
    + return self.Controler.GetBufferState()
    +
    + def Undo(self):
    + self.Controler.LoadPrevious()
    + self.RefreshView()
    +
    + def Redo(self):
    + self.Controler.LoadNext()
    + self.RefreshView()
    +
    + def HasNoModel(self):
    + return False
    +
    + 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:
    + self.StartBuffering()
    + elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
    + self.Controler.EndBuffering()
    + self.StartBuffering()
    + self.CurrentAction = ("Add", event.GetPosition())
    + wx.CallAfter(self.RefreshModel)
    + elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
    + if self.CurrentAction == None:
    + self.StartBuffering()
    + elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
    + self.Controler.EndBuffering()
    + self.StartBuffering()
    + self.CurrentAction = ("Delete", event.GetPosition())
    + wx.CallAfter(self.RefreshModel)
    + event.Skip()
    +
    + def OnDoDrop(self, event):
    + self.ResetBuffer()
    + wx.CallAfter(self.RefreshModel)
    + event.Skip()
    +
    + # 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()
    +
    + def ResetBuffer(self):
    + if self.CurrentAction != None:
    + self.Controler.EndBuffering()
    + self.CurrentAction = None
    +
    + def RefreshView(self):
    + self.ResetBuffer()
    + 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)
    + else:
    + 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()
    +
    + # Tips
    + if event.ShiftDown():
    + pass
    +## 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)')
    + # Code completion
    + else:
    + 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]))
    + else:
    + event.Skip()
    +
    + def OnKillFocus(self, event):
    + self.Editor.AutoCompCancel()
    + event.Skip()
    +
    + def OnUpdateUI(self, evt):
    + # check for matching braces
    + braceAtCaret = -1
    + braceOpposite = -1
    + charBefore = None
    + caretPos = self.Editor.GetCurrentPos()
    +
    + if caretPos > 0:
    + charBefore = self.Editor.GetCharAt(caretPos - 1)
    + styleBefore = self.Editor.GetStyleAt(caretPos - 1)
    +
    + # check before
    + if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
    + braceAtCaret = caretPos - 1
    +
    + # check after
    + if braceAtCaret < 0:
    + charAfter = self.Editor.GetCharAt(caretPos)
    + styleAfter = self.Editor.GetStyleAt(caretPos)
    +
    + if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
    + braceAtCaret = caretPos
    +
    + if braceAtCaret >= 0:
    + braceOpposite = self.Editor.BraceMatch(braceAtCaret)
    +
    + if braceAtCaret != -1 and braceOpposite == -1:
    + self.Editor.BraceBadLight(braceAtCaret)
    + else:
    + self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
    + #pt = self.Editor.PointFromPosition(braceOpposite)
    + #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
    + #print pt
    + #self.Editor.Refresh(False)
    +
    +
    + def OnMarginClick(self, evt):
    + # fold and unfold as needed
    + if evt.GetMargin() == 2:
    + if evt.GetShift() and evt.GetControl():
    + self.FoldAll()
    + else:
    + lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
    +
    + if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
    + if evt.GetShift():
    + self.Editor.SetFoldExpanded(lineClicked, True)
    + self.Expand(lineClicked, True, True, 1)
    + elif evt.GetControl():
    + if self.Editor.GetFoldExpanded(lineClicked):
    + self.Editor.SetFoldExpanded(lineClicked, False)
    + self.Expand(lineClicked, False, True, 0)
    + else:
    + self.Editor.SetFoldExpanded(lineClicked, True)
    + self.Expand(lineClicked, True, True, 100)
    + else:
    + self.Editor.ToggleFold(lineClicked)
    +
    +
    + def FoldAll(self):
    + lineCount = self.Editor.GetLineCount()
    + expanding = True
    +
    + # 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)
    + break
    +
    + lineNum = 0
    +
    + while lineNum < lineCount:
    + level = self.Editor.GetFoldLevel(lineNum)
    + if level & stc.STC_FOLDLEVELHEADERFLAG and \
    + (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
    +
    + if expanding:
    + self.Editor.SetFoldExpanded(lineNum, True)
    + lineNum = self.Expand(lineNum, True)
    + lineNum = lineNum - 1
    + else:
    + lastChild = self.Editor.GetLastChild(lineNum, -1)
    + self.Editor.SetFoldExpanded(lineNum, False)
    +
    + if lastChild > lineNum:
    + self.Editor.HideLines(lineNum+1, lastChild)
    +
    + lineNum = lineNum + 1
    +
    +
    +
    + def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
    + lastChild = self.Editor.GetLastChild(line, level)
    + line = line + 1
    +
    + while line <= lastChild:
    + if force:
    + if visLevels > 0:
    + self.Editor.ShowLines(line, line)
    + else:
    + self.Editor.HideLines(line, line)
    + else:
    + if doExpand:
    + self.Editor.ShowLines(line, line)
    +
    + if level == -1:
    + level = self.Editor.GetFoldLevel(line)
    +
    + if level & stc.STC_FOLDLEVELHEADERFLAG:
    + if force:
    + if visLevels > 1:
    + self.Editor.SetFoldExpanded(line, True)
    + else:
    + self.Editor.SetFoldExpanded(line, False)
    +
    + line = self.Expand(line, doExpand, force, visLevels-1)
    +
    + else:
    + if doExpand and self.Editor.GetFoldExpanded(line):
    + line = self.Expand(line, True, force, visLevels-1)
    + else:
    + line = self.Expand(line, False, force, visLevels-1)
    + else:
    + line = line + 1
    +
    + return line
    +
    + def Cut(self):
    + self.ResetBuffer()
    + self.DisableEvents = True
    + self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
    + self.DisableEvents = False
    + self.RefreshModel()
    + self.RefreshBuffer()
    +
    + def Copy(self):
    + self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
    +
    + def Paste(self):
    + self.ResetBuffer()
    + self.DisableEvents = True
    + self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
    + self.DisableEvents = False
    + self.RefreshModel()
    + self.RefreshBuffer()
    --- /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 @@
    +from py_ext import *
    --- /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("__")]
    +
    +helps = []
    +for name in __all__:
    + helpfilename = path.join(_base_path, name, "README")
    + if path.isfile(helpfilename):
    + helps.append(open(helpfilename).readline().strip())
    + else:
    + helps.append(name)
    --- /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 @@
    +SVGUI HMI
    \ 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 @@
    +from svgui import *
    --- /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 @@
    +// import Nevow.Athena
    +// import Divmod.Base
    +
    +function updateAttr(id, param, value) {
    + Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value);
    +}
    +
    +var svguiWidgets = new Array();
    +
    +var currentObject = null;
    +function setCurrentObject(obj) {
    + currentObject = obj;
    +}
    +function isCurrentObject(obj) {
    + return currentObject == obj;
    +}
    +
    +function getSVGElementById(id) {
    + return document.getElementById(id);
    +}
    +
    +function blockSVGElementDrag(element) {
    + element.addEventListener("draggesture", function(event){event.stopPropagation()}, true);
    +}
    +
    +LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget');
    +LiveSVGPage.LiveSVGWidget.methods(
    +
    + function handleEvent(self, evt) {
    + if (currentObject != null) {
    + currentObject.handleEvent(evt);
    + }
    + },
    +
    + function receiveData(self, data){
    + dataReceived = json_parse(data);
    + gadget = svguiWidgets[dataReceived.id]
    + if (gadget) {
    + gadget.updateValues(json_parse(dataReceived.kwargs));
    + }
    + //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState);
    + },
    +
    + function init(self, arg1){
    + //console.log("Object received : " + arg1);
    + for (ind in arg1) {
    + gad = json_parse(arg1[ind]);
    + args = json_parse(gad.kwargs);
    + gadget = new svguilib[gad.__class__](self, gad.id, args);
    + svguiWidgets[gadget.id]=gadget;
    + //console.log('GADGET :' + gadget);
    + }
    + var elements = document.getElementsByTagName("svg");
    + for (var i = 0; i < elements.length; i++) {
    + elements[i].addEventListener("mouseup", self, false);
    + }
    + //console.log("SVGUIWIDGETS : " + svguiWidgets);
    + }
    +);
    --- /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"
    + productName="Beremiz"
    + productVersion="0.0"
    + creationDateTime="2008-12-14T16:53:26"/>
    + <contentHeader name="Beremiz non-standard POUs library"
    + modificationDateTime="2009-08-12T15:35:33">
    + <coordinateInfo>
    + <fbd>
    + <scaling x="0" y="0"/>
    + </fbd>
    + <ld>
    + <scaling x="0" y="0"/>
    + </ld>
    + <sfc>
    + <scaling x="0" y="0"/>
    + </sfc>
    + </coordinateInfo>
    + </contentHeader>
    + <types>
    + <dataTypes/>
    + <pous>
    + <pou name="GetBoolString" pouType="functionBlock">
    + <interface>
    + <inputVars>
    + <variable name="VALUE">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </inputVars>
    + <outputVars>
    + <variable name="CODE">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </outputVars>
    + </interface>
    + <body>
    + <ST>
    +<![CDATA[IF VALUE THEN
    + CODE := 'True';
    +ELSE
    + CODE := 'False';
    +END_IF;]]>
    + </ST>
    + </body>
    + </pou>
    + <pou name="TextCtrl" pouType="functionBlock">
    + <interface>
    + <localVars>
    + <variable name="ID">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </localVars>
    + <inputVars>
    + <variable name="back_id">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="set_text">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="text">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </inputVars>
    + <localVars>
    + <variable name="SVGUI_TEXTCTRL">
    + <type>
    + <derived name="python_eval"/>
    + </type>
    + </variable>
    + <variable name="setstate_Command">
    + <type>
    + <derived name="python_eval"/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <FBD>
    + <block localId="1" width="193" height="160" typeName="CONCAT">
    + <position x="626" y="122"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="43"/>
    + <connection refLocalId="2">
    + <position x="626" y="165"/>
    + <position x="535" y="165"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="89"/>
    + <connection refLocalId="3">
    + <position x="626" y="211"/>
    + <position x="535" y="211"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN3">
    + <connectionPointIn>
    + <relPosition x="0" y="135"/>
    + <connection refLocalId="6">
    + <position x="626" y="257"/>
    + <position x="532" y="257"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="193" y="43"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="2" height="30" width="460">
    + <position x="75" y="150"/>
    + <connectionPointOut>
    + <relPosition x="460" y="15"/>
    + </connectionPointOut>
    + <expression>'createSVGUIControl("textControl", back_id="'</expression>
    + </inVariable>
    + <inVariable localId="3" height="35" width="85">
    + <position x="450" y="196"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>back_id</expression>
    + </inVariable>
    + <inVariable localId="6" height="30" width="50">
    + <position x="482" y="242"/>
    + <connectionPointOut>
    + <relPosition x="50" y="15"/>
    + </connectionPointOut>
    + <expression>'")'</expression>
    + </inVariable>
    + <block localId="7" width="125" height="115" typeName="python_eval" instanceName="SVGUI_TEXTCTRL">
    + <position x="909" y="75"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="90"/>
    + <connection refLocalId="1" formalParameter="OUT">
    + <position x="909" y="165"/>
    + <position x="819" y="165"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="45"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="90"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="9" height="30" width="70">
    + <position x="799" y="70"/>
    + <connectionPointOut>
    + <relPosition x="70" y="15"/>
    + </connectionPointOut>
    + <expression>BOOL#1</expression>
    + </inVariable>
    + <outVariable localId="10" height="30" width="30">
    + <position x="1094" y="150"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="7" formalParameter="RESULT">
    + <position x="1094" y="165"/>
    + <position x="1034" y="165"/>
    + </connection>
    + </connectionPointIn>
    + <expression>ID</expression>
    + </outVariable>
    + <connector name="CREATED" localId="11" height="30" width="110">
    + <position x="1096" y="105"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="7" formalParameter="ACK">
    + <position x="1096" y="120"/>
    + <position x="1034" y="120"/>
    + </connection>
    + </connectionPointIn>
    + </connector>
    + <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
    + <position x="957" y="472"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="12" formalParameter="OUT">
    + <position x="957" y="582"/>
    + <position x="822" y="582"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="50"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="110"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <continuation name="CREATED" localId="5" height="30" width="110">
    + <position x="589" y="429"/>
    + <connectionPointOut>
    + <relPosition x="110" y="15"/>
    + </connectionPointOut>
    + </continuation>
    + <block localId="12" width="186" height="288" typeName="CONCAT">
    + <position x="636" y="536"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="46"/>
    + <connection refLocalId="14">
    + <position x="636" y="582"/>
    + <position x="526" y="582"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="99"/>
    + <connection refLocalId="8">
    + <position x="636" y="635"/>
    + <position x="526" y="635"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN3">
    + <connectionPointIn>
    + <relPosition x="0" y="152"/>
    + <connection refLocalId="15">
    + <position x="636" y="688"/>
    + <position x="527" y="688"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN4">
    + <connectionPointIn>
    + <relPosition x="0" y="205"/>
    + <connection refLocalId="32">
    + <position x="636" y="741"/>
    + <position x="528" y="741"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN5">
    + <connectionPointIn>
    + <relPosition x="0" y="258"/>
    + <connection refLocalId="16">
    + <position x="636" y="794"/>
    + <position x="528" y="794"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="186" y="46"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="8" height="30" width="53">
    + <position x="473" y="620"/>
    + <connectionPointOut>
    + <relPosition x="53" y="15"/>
    + </connectionPointOut>
    + <expression>ID</expression>
    + </inVariable>
    + <inVariable localId="13" height="35" width="100">
    + <position x="599" y="469"/>
    + <connectionPointOut>
    + <relPosition x="100" y="17"/>
    + </connectionPointOut>
    + <expression>set_text</expression>
    + </inVariable>
    + <inVariable localId="14" height="30" width="120">
    + <position x="406" y="567"/>
    + <connectionPointOut>
    + <relPosition x="120" y="15"/>
    + </connectionPointOut>
    + <expression>'setAttr('</expression>
    + </inVariable>
    + <inVariable localId="15" height="30" width="122">
    + <position x="405" y="673"/>
    + <connectionPointOut>
    + <relPosition x="122" y="15"/>
    + </connectionPointOut>
    + <expression>',"text","'</expression>
    + </inVariable>
    + <inVariable localId="16" height="30" width="50">
    + <position x="478" y="779"/>
    + <connectionPointOut>
    + <relPosition x="50" y="15"/>
    + </connectionPointOut>
    + <expression>'")'</expression>
    + </inVariable>
    + <block localId="31" width="75" height="105" typeName="AND">
    + <position x="782" y="403"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="41"/>
    + <connection refLocalId="5">
    + <position x="782" y="444"/>
    + <position x="699" y="444"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="83"/>
    + <connection refLocalId="13">
    + <position x="782" y="486"/>
    + <position x="699" y="486"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="75" y="41"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="32" height="30" width="90">
    + <position x="438" y="726"/>
    + <connectionPointOut>
    + <relPosition x="90" y="15"/>
    + </connectionPointOut>
    + <expression>text</expression>
    + </inVariable>
    + </FBD>
    + </body>
    + </pou>
    + <pou name="Button" pouType="functionBlock">
    + <interface>
    + <localVars>
    + <variable name="ID">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </localVars>
    + <inputVars>
    + <variable name="back_id">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="sele_id">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="toggle">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="set_state">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="state_in">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </inputVars>
    + <outputVars>
    + <variable name="state_out">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </outputVars>
    + <localVars>
    + <variable name="init_Command">
    + <type>
    + <derived name="python_eval"/>
    + </type>
    + </variable>
    + <variable name="GetButtonState">
    + <type>
    + <derived name="GetBoolString"/>
    + </type>
    + </variable>
    + <variable name="setstate_Command">
    + <type>
    + <derived name="python_eval"/>
    + </type>
    + </variable>
    + <variable name="getstate_Command">
    + <type>
    + <derived name="python_poll"/>
    + </type>
    + </variable>
    + <variable name="GetButtonToggle">
    + <type>
    + <derived name="GetBoolString"/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <FBD>
    + <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
    + <position x="838" y="32"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="10">
    + <position x="838" y="82"/>
    + <position x="781" y="82"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="2" formalParameter="OUT">
    + <position x="838" y="142"/>
    + <position x="641" y="142"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="50"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="110"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <block localId="2" width="150" height="442" typeName="CONCAT">
    + <position x="491" y="92"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="3">
    + <position x="491" y="142"/>
    + <position x="433" y="142"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="11">
    + <position x="491" y="202"/>
    + <position x="431" y="202"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN3">
    + <connectionPointIn>
    + <relPosition x="0" y="170"/>
    + <connection refLocalId="5">
    + <position x="491" y="262"/>
    + <position x="431" y="262"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN4">
    + <connectionPointIn>
    + <relPosition x="0" y="230"/>
    + <connection refLocalId="12">
    + <position x="491" y="322"/>
    + <position x="430" y="322"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN5">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN6">
    + <connectionPointIn>
    + <relPosition x="0" y="350"/>
    + <connection refLocalId="24" formalParameter="CODE">
    + <position x="491" y="442"/>
    + <position x="429" y="442"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN7">
    + <connectionPointIn>
    + <relPosition x="0" y="410"/>
    + <connection refLocalId="9">
    + <position x="491" y="502"/>
    + <position x="430" y="502"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="150" y="50"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="3" height="30" width="400">
    + <position x="33" y="127"/>
    + <connectionPointOut>
    + <relPosition x="400" y="15"/>
    + </connectionPointOut>
    + <expression>'createSVGUIControl("button",back_id="'</expression>
    + </inVariable>
    + <inVariable localId="5" height="30" width="140">
    + <position x="291" y="247"/>
    + <connectionPointOut>
    + <relPosition x="140" y="15"/>
    + </connectionPointOut>
    + <expression>'",sele_id="'</expression>
    + </inVariable>
    + <inVariable localId="9" height="30" width="180">
    + <position x="250" y="487"/>
    + <connectionPointOut>
    + <relPosition x="180" y="15"/>
    + </connectionPointOut>
    + <expression>',active=True)'</expression>
    + </inVariable>
    + <inVariable localId="10" height="30" width="70">
    + <position x="711" y="67"/>
    + <connectionPointOut>
    + <relPosition x="70" y="15"/>
    + </connectionPointOut>
    + <expression>BOOL#1</expression>
    + </inVariable>
    + <inVariable localId="11" height="35" width="85">
    + <position x="346" y="187"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>back_id</expression>
    + </inVariable>
    + <inVariable localId="12" height="35" width="85">
    + <position x="345" y="307"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>sele_id</expression>
    + </inVariable>
    + <inVariable localId="13" height="35" width="100">
    + <position x="452" y="639"/>
    + <connectionPointOut>
    + <relPosition x="100" y="15"/>
    + </connectionPointOut>
    + <expression>set_state</expression>
    + </inVariable>
    + <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonState">
    + <position x="239" y="897"/>
    + <inputVariables>
    + <variable formalParameter="VALUE">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="32">
    + <position x="239" y="927"/>
    + <position x="181" y="927"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="CODE">
    + <connectionPointOut>
    + <relPosition x="140" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <outVariable localId="29" height="30" width="53">
    + <position x="1015" y="127"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="1" formalParameter="RESULT">
    + <position x="1015" y="142"/>
    + <position x="963" y="142"/>
    + </connection>
    + </connectionPointIn>
    + <expression>ID</expression>
    + </outVariable>
    + <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
    + <position x="810" y="640"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="7" formalParameter="OUT">
    + <position x="810" y="750"/>
    + <position x="643" y="750"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="50"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="110"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <connector name="CREATED" localId="30" height="30" width="110">
    + <position x="1014" y="67"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="1" formalParameter="ACK">
    + <position x="1014" y="82"/>
    + <position x="963" y="82"/>
    + </connection>
    + </connectionPointIn>
    + </connector>
    + <continuation name="CREATED" localId="6" height="30" width="110">
    + <position x="442" y="597"/>
    + <connectionPointOut>
    + <relPosition x="110" y="15"/>
    + </connectionPointOut>
    + </continuation>
    + <block localId="31" width="75" height="105" typeName="AND">
    + <position x="635" y="571"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="41"/>
    + <connection refLocalId="6">
    + <position x="635" y="612"/>
    + <position x="552" y="612"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="83"/>
    + <connection refLocalId="13">
    + <position x="635" y="654"/>
    + <position x="552" y="654"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="75" y="41"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="32" height="30" width="90">
    + <position x="91" y="912"/>
    + <connectionPointOut>
    + <relPosition x="90" y="15"/>
    + </connectionPointOut>
    + <expression>state_in</expression>
    + </inVariable>
    + <outVariable localId="33" height="30" width="100">
    + <position x="1334" y="1184"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="26" formalParameter="OUT">
    + <position x="1334" y="1199"/>
    + <position x="1286" y="1199"/>
    + </connection>
    + </connectionPointIn>
    + <expression>state_out</expression>
    + </outVariable>
    + <block localId="7" width="150" height="319" typeName="CONCAT">
    + <position x="493" y="701"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="49"/>
    + <connection refLocalId="14">
    + <position x="493" y="750"/>
    + <position x="379" y="750"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN3">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN4">
    + <connectionPointIn>
    + <relPosition x="0" y="226"/>
    + <connection refLocalId="28" formalParameter="CODE">
    + <position x="493" y="927"/>
    + <position x="379" y="927"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN5">
    + <connectionPointIn>
    + <relPosition x="0" y="285"/>
    + <connection refLocalId="16">
    + <position x="493" y="986"/>
    + <position x="377" y="986"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="150" y="49"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="8" height="30" width="53">
    + <position x="326" y="788"/>
    + <connectionPointOut>
    + <relPosition x="53" y="15"/>
    + </connectionPointOut>
    + <expression>ID</expression>
    + </inVariable>
    + <inVariable localId="14" height="30" width="120">
    + <position x="259" y="735"/>
    + <connectionPointOut>
    + <relPosition x="120" y="15"/>
    + </connectionPointOut>
    + <expression>'setAttr('</expression>
    + </inVariable>
    + <inVariable localId="15" height="30" width="122">
    + <position x="257" y="840"/>
    + <connectionPointOut>
    + <relPosition x="122" y="15"/>
    + </connectionPointOut>
    + <expression>',"state",'</expression>
    + </inVariable>
    + <inVariable localId="16" height="30" width="41">
    + <position x="336" y="971"/>
    + <connectionPointOut>
    + <relPosition x="41" y="15"/>
    + </connectionPointOut>
    + <expression>')'</expression>
    + </inVariable>
    + <block localId="17" width="125" height="140" typeName="python_poll" instanceName="getstate_Command">
    + <position x="801" y="1089"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="22" formalParameter="OUT">
    + <position x="801" y="1199"/>
    + <position x="643" y="1199"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="50"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="110"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <block localId="25" width="145" height="45" typeName="STRING_TO_INT">
    + <position x="966" y="1169"/>
    + <inputVariables>
    + <variable formalParameter="IN">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="17" formalParameter="RESULT">
    + <position x="966" y="1199"/>
    + <position x="926" y="1199"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="145" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <block localId="26" width="125" height="45" typeName="INT_TO_BOOL">
    + <position x="1161" y="1169"/>
    + <inputVariables>
    + <variable formalParameter="IN">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="25" formalParameter="OUT">
    + <position x="1161" y="1199"/>
    + <position x="1111" y="1199"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="125" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <continuation name="CREATED" localId="18" height="30" width="110">
    + <position x="610" y="1084"/>
    + <connectionPointOut>
    + <relPosition x="110" y="15"/>
    + </connectionPointOut>
    + </continuation>
    + <inVariable localId="19" height="30" width="53">
    + <position x="383" y="1238"/>
    + <connectionPointOut>
    + <relPosition x="53" y="15"/>
    + </connectionPointOut>
    + <expression>ID</expression>
    + </inVariable>
    + <inVariable localId="20" height="30" width="150">
    + <position x="286" y="1184"/>
    + <connectionPointOut>
    + <relPosition x="150" y="15"/>
    + </connectionPointOut>
    + <expression>'int(getAttr('</expression>
    + </inVariable>
    + <inVariable localId="21" height="30" width="190">
    + <position x="246" y="1292"/>
    + <connectionPointOut>
    + <relPosition x="190" y="15"/>
    + </connectionPointOut>
    + <expression>',"state",False))'</expression>
    + </inVariable>
    + <block localId="22" width="150" height="183" typeName="CONCAT">
    + <position x="493" y="1152"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="47"/>
    + <connection refLocalId="20">
    + <position x="493" y="1199"/>
    + <position x="436" y="1199"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="101"/>
    + <connection refLocalId="19">
    + <position x="493" y="1253"/>
    + <position x="436" y="1253"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN3">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="150" y="47"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="23" height="30" width="130">
    + <position x="300" y="355"/>
    + <connectionPointOut>
    + <relPosition x="130" y="15"/>
    + </connectionPointOut>
    + <expression>'",toggle='</expression>
    + </inVariable>
    + <block localId="24" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonToggle">
    + <position x="289" y="412"/>
    + <inputVariables>
    + <variable formalParameter="VALUE">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="27">
    + <position x="289" y="442"/>
    + <position x="220" y="442"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="CODE">
    + <connectionPointOut>
    + <relPosition x="140" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="27" height="30" width="90">
    + <position x="130" y="427"/>
    + <connectionPointOut>
    + <relPosition x="90" y="15"/>
    + </connectionPointOut>
    + <expression>toggle</expression>
    + </inVariable>
    + </FBD>
    + </body>
    + </pou>
    + <pou name="Led" pouType="functionBlock">
    + <interface>
    + <localVars>
    + <variable name="ID">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </localVars>
    + <inputVars>
    + <variable name="back_id">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="sele_id">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="state_in">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </inputVars>
    + <localVars>
    + <variable name="init_Command">
    + <type>
    + <derived name="python_eval"/>
    + </type>
    + </variable>
    + <variable name="setstate_Command">
    + <type>
    + <derived name="python_poll"/>
    + </type>
    + </variable>
    + <variable name="GetLedState">
    + <type>
    + <derived name="GetBoolString"/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <FBD>
    + <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
    + <position x="810" y="30"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="10">
    + <position x="810" y="80"/>
    + <position x="753" y="80"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="2" formalParameter="OUT">
    + <position x="810" y="140"/>
    + <position x="640" y="140"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="50"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="110"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <block localId="2" width="150" height="322" typeName="CONCAT">
    + <position x="490" y="90"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="50"/>
    + <connection refLocalId="3">
    + <position x="490" y="140"/>
    + <position x="415" y="140"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="11">
    + <position x="490" y="200"/>
    + <position x="415" y="200"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN3">
    + <connectionPointIn>
    + <relPosition x="0" y="170"/>
    + <connection refLocalId="5">
    + <position x="490" y="260"/>
    + <position x="415" y="260"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN4">
    + <connectionPointIn>
    + <relPosition x="0" y="230"/>
    + <connection refLocalId="12">
    + <position x="490" y="320"/>
    + <position x="414" y="320"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN5">
    + <connectionPointIn>
    + <relPosition x="0" y="290"/>
    + <connection refLocalId="9">
    + <position x="490" y="380"/>
    + <position x="414" y="380"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="150" y="50"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="3" height="30" width="400">
    + <position x="15" y="125"/>
    + <connectionPointOut>
    + <relPosition x="400" y="15"/>
    + </connectionPointOut>
    + <expression>'createSVGUIControl("button",back_id="'</expression>
    + </inVariable>
    + <block localId="4" width="125" height="140" typeName="python_poll" instanceName="setstate_Command">
    + <position x="782" y="536"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="110"/>
    + <connection refLocalId="7" formalParameter="OUT">
    + <position x="782" y="646"/>
    + <position x="615" y="646"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="50"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="110"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="5" height="30" width="140">
    + <position x="275" y="245"/>
    + <connectionPointOut>
    + <relPosition x="140" y="15"/>
    + </connectionPointOut>
    + <expression>'",sele_id="'</expression>
    + </inVariable>
    + <continuation name="CREATED" localId="6" height="30" width="110">
    + <position x="492" y="537"/>
    + <connectionPointOut>
    + <relPosition x="110" y="15"/>
    + </connectionPointOut>
    + </continuation>
    + <block localId="7" width="150" height="319" typeName="CONCAT">
    + <position x="465" y="597"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="49"/>
    + <connection refLocalId="14">
    + <position x="465" y="646"/>
    + <position x="351" y="646"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN3">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN4">
    + <connectionPointIn>
    + <relPosition x="0" y="226"/>
    + <connection refLocalId="28" formalParameter="CODE">
    + <position x="465" y="823"/>
    + <position x="351" y="823"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN5">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="150" y="49"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="8" height="30" width="53">
    + <position x="298" y="684"/>
    + <connectionPointOut>
    + <relPosition x="53" y="15"/>
    + </connectionPointOut>
    + <expression>ID</expression>
    + </inVariable>
    + <inVariable localId="9" height="30" width="300">
    + <position x="124" y="365"/>
    + <connectionPointOut>
    + <relPosition x="300" y="15"/>
    + </connectionPointOut>
    + <expression>'",toggle=True,active=False)'</expression>
    + </inVariable>
    + <inVariable localId="10" height="30" width="70">
    + <position x="683" y="65"/>
    + <connectionPointOut>
    + <relPosition x="70" y="15"/>
    + </connectionPointOut>
    + <expression>BOOL#1</expression>
    + </inVariable>
    + <inVariable localId="11" height="35" width="85">
    + <position x="330" y="185"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>back_id</expression>
    + </inVariable>
    + <inVariable localId="12" height="35" width="85">
    + <position x="329" y="305"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>sele_id</expression>
    + </inVariable>
    + <inVariable localId="14" height="30" width="120">
    + <position x="231" y="631"/>
    + <connectionPointOut>
    + <relPosition x="120" y="15"/>
    + </connectionPointOut>
    + <expression>'setAttr('</expression>
    + </inVariable>
    + <inVariable localId="15" height="30" width="122">
    + <position x="229" y="736"/>
    + <connectionPointOut>
    + <relPosition x="122" y="15"/>
    + </connectionPointOut>
    + <expression>',"state",'</expression>
    + </inVariable>
    + <inVariable localId="16" height="30" width="41">
    + <position x="310" y="868"/>
    + <connectionPointOut>
    + <relPosition x="41" y="15"/>
    + </connectionPointOut>
    + <expression>')'</expression>
    + </inVariable>
    + <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetLedState">
    + <position x="211" y="793"/>
    + <inputVariables>
    + <variable formalParameter="VALUE">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="32">
    + <position x="211" y="823"/>
    + <position x="153" y="823"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="CODE">
    + <connectionPointOut>
    + <relPosition x="140" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <outVariable localId="29" height="30" width="53">
    + <position x="987" y="125"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="1" formalParameter="RESULT">
    + <position x="987" y="140"/>
    + <position x="935" y="140"/>
    + </connection>
    + </connectionPointIn>
    + <expression>ID</expression>
    + </outVariable>
    + <connector name="CREATED" localId="30" height="30" width="110">
    + <position x="986" y="65"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="1" formalParameter="ACK">
    + <position x="986" y="80"/>
    + <position x="935" y="80"/>
    + </connection>
    + </connectionPointIn>
    + </connector>
    + <inVariable localId="32" height="30" width="90">
    + <position x="63" y="808"/>
    + <connectionPointOut>
    + <relPosition x="90" y="15"/>
    + </connectionPointOut>
    + <expression>state_in</expression>
    + </inVariable>
    + </FBD>
    + </body>
    + </pou>
    + </pous>
    + </types>
    + <instances>
    + <configurations/>
    + </instances>
    +</project>
    --- /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 @@
    +from pyjs import *
    +
    --- /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 @@
    +#!/usr/bin/env python
    +
    +import sys
    +import os
    +import shutil
    +from copy import copy
    +from os.path import join, dirname, basename, abspath, split, isfile, isdir
    +from optparse import OptionParser
    +import pyjs
    +from cStringIO import StringIO
    +try:
    + # Python 2.5 and above
    + from hashlib import md5
    +except:
    + import md5
    +import re
    +
    +usage = """
    + usage: %prog [options] <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
    +# -------------+-----------------------+----------------------+----------------------
    +# IE6 | ie6 | IE6 | ie6
    +# Opera | opera | Opera | opera
    +# Safari | safari | Safari | safari
    +# -- | gecko1_8 | Mozilla | mozilla
    +# -- | gecko | OldMoz | oldmoz
    +# Standard | all | (default code) | all
    +# Mozilla | gecko1_8, gecko | -- | --
    +# Old | safari, gecko, opera | -- | --
    +
    +version = "%prog pyjamas version 2006-08-19"
    +
    +# these names in lowercase need match the strings
    +# returned by "provider$user.agent" in order to be selected corretly
    +app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla']
    +
    +# usually defaults to e.g. /usr/share/pyjamas
    +_data_dir = os.path.join(pyjs.prefix, "share/pyjamas")
    +
    +
    +# .cache.html files produces look like this
    +CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$')
    +
    +# ok these are the three "default" library directories, containing
    +# the builtins (str, List, Dict, ord, round, len, range etc.)
    +# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.)
    +# and the contributed addons
    +
    +for p in ["library/builtins",
    + "library",
    + "addons"]:
    + p = os.path.join(_data_dir, p)
    + if os.path.isdir(p):
    + pyjs.path.append(p)
    +
    +
    +def read_boilerplate(data_dir, filename):
    + return open(join(data_dir, "builder/boilerplate", filename)).read()
    +
    +def copy_boilerplate(data_dir, filename, output_dir):
    + filename = join(data_dir, "builder/boilerplate", filename)
    + shutil.copy(filename, output_dir)
    +
    +
    +# taken and modified from python2.4
    +def copytree_exists(src, dst, symlinks=False):
    + if not os.path.exists(src):
    + return
    +
    + names = os.listdir(src)
    + try:
    + os.mkdir(dst)
    + except:
    + pass
    +
    + errors = []
    + for name in names:
    + if name.startswith('CVS'):
    + continue
    + if name.startswith('.git'):
    + continue
    + if name.startswith('.svn'):
    + continue
    +
    + srcname = os.path.join(src, name)
    + dstname = os.path.join(dst, name)
    + try:
    + if symlinks and os.path.islink(srcname):
    + linkto = os.readlink(srcname)
    + os.symlink(linkto, dstname)
    + elif isdir(srcname):
    + copytree_exists(srcname, dstname, symlinks)
    + else:
    + shutil.copy2(srcname, dstname)
    + except (IOError, os.error), why:
    + errors.append((srcname, dstname, why))
    + if errors:
    + print errors
    +
    +def check_html_file(source_file, dest_path):
    + """ Checks if a base HTML-file is available in the PyJamas
    + output directory.
    + If the HTML-file isn't available, it will be created.
    +
    + If a CSS-file with the same name is available
    + in the output directory, a reference to this CSS-file
    + is included.
    +
    + If no CSS-file is found, this function will look for a special
    + CSS-file in the output directory, with the name
    + "pyjamas_default.css", and if found it will be referenced
    + in the generated HTML-file.
    +
    + [thank you to stef mientki for contributing this function]
    + """
    +
    + base_html = """\
    +<html>
    + <!-- auto-generated html - you should consider editing and
    + adapting this to suit your requirements
    + -->
    + <head>
    + <meta name="pygwt:module" content="%(modulename)s">
    + %(css)s
    + <title>%(title)s</title>
    + </head>
    + <body bgcolor="white">
    + <script language="javascript" src="pygwt.js"></script>
    + </body>
    +</html>
    +"""
    +
    + filename = os.path.split ( source_file )[1]
    + mod_name = os.path.splitext ( filename )[0]
    + file_name = os.path.join ( dest_path, mod_name + '.html' )
    +
    + # if html file in output directory exists, leave it alone.
    + if os.path.exists ( file_name ):
    + return 0
    +
    + if os.path.exists (
    + os.path.join ( dest_path, mod_name + '.css' ) ) :
    + css = "<link rel='stylesheet' href='" + mod_name + ".css'>"
    + elif os.path.exists (
    + os.path.join ( dest_path, 'pyjamas_default.css' ) ) :
    + css = "<link rel='stylesheet' href='pyjamas_default.css'>"
    +
    + else:
    + css = ''
    +
    + title = 'PyJamas Auto-Generated HTML file ' + mod_name
    +
    + base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css}
    +
    + fh = open (file_name, 'w')
    + fh.write (base_html)
    + fh.close ()
    +
    + return 1
    +
    +
    +def build(app_name, output, js_includes=(), debug=False, dynamic=0,
    + data_dir=None, cache_buster=False, optimize=False):
    +
    + # make sure the output directory is always created in the current working
    + # directory or at the place given if it is an absolute path.
    + output = os.path.abspath(output)
    + msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals()
    + if debug:
    + msg += " with debugging statements"
    + print msg
    +
    + # check the output directory
    + if os.path.exists(output) and not os.path.isdir(output):
    + print >>sys.stderr, "Output destination %s exists and is not a directory" % output
    + return
    + if not os.path.isdir(output):
    + try:
    + print "Creating output directory"
    + os.mkdir(output)
    + except StandardError, e:
    + print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e)
    +
    + ## public dir
    + for p in pyjs.path:
    + pub_dir = join(p, 'public')
    + if isdir(pub_dir):
    + print "Copying: public directory of library %r" % p
    + copytree_exists(pub_dir, output)
    +
    + ## AppName.html - can be in current or public directory
    + html_input_filename = app_name + ".html"
    + html_output_filename = join(output, basename(html_input_filename))
    + if os.path.isfile(html_input_filename):
    + if not os.path.isfile(html_output_filename) or \
    + os.path.getmtime(html_input_filename) > \
    + os.path.getmtime(html_output_filename):
    + try:
    + shutil.copy(html_input_filename, html_output_filename)
    + except:
    + print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename
    +
    + print "Copying: %(html_input_filename)s" % locals()
    +
    + if check_html_file(html_input_filename, output):
    + print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename
    +
    + ## pygwt.js
    +
    + print "Copying: pygwt.js"
    +
    + pygwt_js_template = read_boilerplate(data_dir, "pygwt.js")
    + pygwt_js_output = open(join(output, "pygwt.js"), "w")
    +
    + print >>pygwt_js_output, pygwt_js_template
    +
    + pygwt_js_output.close()
    +
    + ## Images
    +
    + print "Copying: Images and History"
    + copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_topleft.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_topright.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output)
    + copy_boilerplate(data_dir, "corner_dialog_edge.png", output)
    + copy_boilerplate(data_dir, "tree_closed.gif", output)
    + copy_boilerplate(data_dir, "tree_open.gif", output)
    + copy_boilerplate(data_dir, "tree_white.gif", output)
    + copy_boilerplate(data_dir, "history.html", output)
    +
    +
    + ## all.cache.html
    + app_files = generateAppFiles(data_dir, js_includes, app_name, debug,
    + output, dynamic, cache_buster, optimize)
    +
    + ## AppName.nocache.html
    +
    + print "Creating: %(app_name)s.nocache.html" % locals()
    +
    + home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html")
    + home_nocache_html_output = open(join(output, app_name + ".nocache.html"),
    + "w")
    +
    + # the selector templ is added to the selectScript function
    + select_tmpl = """O(["true","%s"],"%s");"""
    + script_selectors = StringIO()
    +
    + for platform, file_prefix in app_files:
    + print >> script_selectors, select_tmpl % (platform, file_prefix)
    +
    + print >>home_nocache_html_output, home_nocache_html_template % dict(
    + app_name = app_name,
    + script_selectors = script_selectors.getvalue(),
    + )
    +
    + home_nocache_html_output.close()
    +
    + print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals()
    +
    +
    +def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic,
    + cache_buster, optimize):
    +
    + all_cache_html_template = read_boilerplate(data_dir, "all.cache.html")
    + mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html")
    +
    + # clean out the old ones first
    + for name in os.listdir(output):
    + if CACHE_HTML_PAT.match(name):
    + p = join(output, name)
    + print "Deleting existing app file %s" % p
    + os.unlink(p)
    +
    + app_files = []
    + tmpl = read_boilerplate(data_dir, "all.cache.html")
    + parser = pyjs.PlatformParser("platform")
    + app_headers = ''
    + scripts = ['<script type="text/javascript" src="%s"></script>'%script \
    + for script in js_includes]
    + app_body = '\n'.join(scripts)
    +
    + mod_code = {}
    + mod_libs = {}
    + modules = {}
    + app_libs = {}
    + early_app_libs = {}
    + app_code = {}
    + overrides = {}
    + pover = {}
    + app_modnames = {}
    + mod_levels = {}
    +
    + # First, generate all the code.
    + # Second, (dynamic only), post-analyse the places where modules
    + # haven't changed
    + # Third, write everything out.
    +
    + for platform in app_platforms:
    +
    + mod_code[platform] = {}
    + mod_libs[platform] = {}
    + modules[platform] = []
    + pover[platform] = {}
    + app_libs[platform] = ''
    + early_app_libs[platform] = ''
    + app_code[platform] = {}
    + app_modnames[platform] = {}
    +
    + # Application.Platform.cache.html
    +
    + parser.setPlatform(platform)
    + app_translator = pyjs.AppTranslator(
    + parser=parser, dynamic=dynamic, optimize=optimize)
    + early_app_libs[platform], appcode = \
    + app_translator.translate(None, is_app=False,
    + debug=debug,
    + library_modules=['dynamicajax.js',
    + '_pyjs.js', 'sys',
    + 'pyjslib'])
    + pover[platform].update(app_translator.overrides.items())
    + for mname, name in app_translator.overrides.items():
    + pd = overrides.setdefault(mname, {})
    + pd[platform] = name
    +
    + print appcode
    + #mod_code[platform][app_name] = appcode
    +
    + # platform.Module.cache.js
    +
    + modules_done = ['pyjslib', 'sys', '_pyjs.js']
    + #modules_to_do = [app_name] + app_translator.library_modules
    + modules_to_do = [app_name] + app_translator.library_modules
    +
    + dependencies = {}
    +
    + deps = map(pyjs.strip_py, modules_to_do)
    + for d in deps:
    + sublist = add_subdeps(dependencies, d)
    + modules_to_do += sublist
    + deps = uniquify(deps)
    + #dependencies[app_name] = deps
    +
    + modules[platform] = modules_done + modules_to_do
    +
    + while modules_to_do:
    +
    + #print "modules to do", modules_to_do
    +
    + mn = modules_to_do.pop()
    + mod_name = pyjs.strip_py(mn)
    +
    + if mod_name in modules_done:
    + continue
    +
    + modules_done.append(mod_name)
    +
    + mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name)
    +
    + parser.setPlatform(platform)
    + mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize)
    + mod_libs[platform][mod_name], mod_code[platform][mod_name] = \
    + mod_translator.translate(mod_name,
    + is_app=False,
    + debug=debug)
    + pover[platform].update(mod_translator.overrides.items())
    + for mname, name in mod_translator.overrides.items():
    + pd = overrides.setdefault(mname, {})
    + pd[platform] = name
    +
    + mods = mod_translator.library_modules
    + modules_to_do += mods
    + modules[platform] += mods
    +
    + deps = map(pyjs.strip_py, mods)
    + sd = subdeps(mod_name)
    + if len(sd) > 1:
    + deps += sd[:-1]
    + while mod_name in deps:
    + deps.remove(mod_name)
    +
    + #print
    + #print
    + #print "modname preadd:", mod_name, deps
    + #print
    + #print
    + for d in deps:
    + sublist = add_subdeps(dependencies, d)
    + modules_to_do += sublist
    + modules_to_do += add_subdeps(dependencies, mod_name)
    + #print "modname:", mod_name, deps
    + deps = uniquify(deps)
    + #print "modname:", mod_name, deps
    + dependencies[mod_name] = deps
    +
    + # work out the dependency ordering of the modules
    +
    + mod_levels[platform] = make_deps(None, dependencies, modules_done)
    +
    + # now write everything out
    +
    + for platform in app_platforms:
    +
    + early_app_libs_ = early_app_libs[platform]
    + app_libs_ = app_libs[platform]
    + app_code_ = app_code[platform]
    + #modules_ = filter_mods(app_name, modules[platform])
    + mods = flattenlist(mod_levels[platform])
    + mods.reverse()
    + modules_ = filter_mods(None, mods)
    +
    + for mod_name in modules_:
    +
    + mod_code_ = mod_code[platform][mod_name]
    +
    + mod_name = pyjs.strip_py(mod_name)
    +
    + override_name = "%s.%s" % (platform.lower(), mod_name)
    + if pover[platform].has_key(override_name):
    + mod_cache_name = "%s.cache.js" % (override_name)
    + else:
    + mod_cache_name = "%s.cache.js" % (mod_name)
    +
    + print "Creating: " + mod_cache_name
    +
    + modlevels = make_deps(None, dependencies, dependencies[mod_name])
    +
    + modnames = []
    +
    + for md in modlevels:
    + mnames = map(lambda x: "'%s'" % x, md)
    + mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
    + modnames.append(mnames)
    +
    + modnames.reverse()
    + modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames)
    +
    + # convert the overrides
    +
    + overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
    + overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
    +
    + if dynamic:
    + mod_cache_html_output = open(join(output, mod_cache_name), "w")
    + else:
    + mod_cache_html_output = StringIO()
    +
    + print >>mod_cache_html_output, mod_cache_html_template % dict(
    + mod_name = mod_name,
    + app_name = app_name,
    + modnames = modnames,
    + overrides = overnames,
    + mod_libs = mod_libs[platform][mod_name],
    + dynamic = dynamic,
    + mod_code = mod_code_,
    + )
    +
    + if dynamic:
    + mod_cache_html_output.close()
    + else:
    + mod_cache_html_output.seek(0)
    + app_libs_ += mod_cache_html_output.read()
    +
    + # write out the dependency ordering of the modules
    +
    + app_modnames = []
    +
    + for md in mod_levels[platform]:
    + mnames = map(lambda x: "'%s'" % x, md)
    + mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
    + app_modnames.append(mnames)
    +
    + app_modnames.reverse()
    + app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames)
    +
    + # convert the overrides
    +
    + overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
    + overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
    +
    + #print "platform names", platform, overnames
    + #print pover
    +
    + # now write app.allcache including dependency-ordered list of
    + # library modules
    +
    + file_contents = all_cache_html_template % dict(
    + app_name = app_name,
    + early_app_libs = early_app_libs_,
    + app_libs = app_libs_,
    + app_code = app_code_,
    + app_body = app_body,
    + overrides = overnames,
    + platform = platform.lower(),
    + dynamic = dynamic,
    + app_modnames = app_modnames,
    + app_headers = app_headers
    + )
    + if cache_buster:
    + digest = md5.new(file_contents).hexdigest()
    + file_name = "%s.%s.%s" % (platform.lower(), app_name, digest)
    + else:
    + file_name = "%s.%s" % (platform.lower(), app_name)
    + file_name += ".cache.html"
    + out_path = join(output, file_name)
    + out_file = open(out_path, 'w')
    + out_file.write(file_contents)
    + out_file.close()
    + app_files.append((platform.lower(), file_name))
    + print "Created app file %s:%s: %s" % (
    + app_name, platform, out_path)
    +
    + return app_files
    +
    +def flattenlist(ll):
    + res = []
    + for l in ll:
    + res += l
    + return res
    +
    +# creates sub-dependencies e.g. pyjamas.ui.Widget
    +# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
    +def subdeps(m):
    + d = []
    + m = m.split(".")
    + for i in range(0, len(m)):
    + d.append('.'.join(m[:i+1]))
    + return d
    +
    +import time
    +
    +def add_subdeps(deps, mod_name):
    + sd = subdeps(mod_name)
    + if len(sd) == 1:
    + return []
    + #print "subdeps", mod_name, sd
    + #print "deps", deps
    + res = []
    + for i in range(0, len(sd)-1):
    + parent = sd[i]
    + child = sd[i+1]
    + l = deps.get(child, [])
    + l.append(parent)
    + deps[child] = l
    + if parent not in res:
    + res.append(parent)
    + #print deps
    + return res
    +
    +# makes unique and preserves list order
    +def uniquify(md):
    + res = []
    + for m in md:
    + if m not in res:
    + res.append(m)
    + return res
    +
    +def filter_mods(app_name, md):
    + while 'sys' in md:
    + md.remove('sys')
    + while 'pyjslib' in md:
    + md.remove('pyjslib')
    + while app_name in md:
    + md.remove(app_name)
    + md = filter(lambda x: not x.endswith('.js'), md)
    + md = map(pyjs.strip_py, md)
    +
    + return uniquify(md)
    +
    +def filter_deps(app_name, deps):
    +
    + res = {}
    + for (k, l) in deps.items():
    + mods = filter_mods(k, l)
    + while k in mods:
    + mods.remove(k)
    + res[k] = mods
    + return res
    +
    +def has_nodeps(mod, deps):
    + if not deps.has_key(mod) or not deps[mod]:
    + return True
    + return False
    +
    +def nodeps_list(mod_list, deps):
    + res = []
    + for mod in mod_list:
    + if has_nodeps(mod, deps):
    + res.append(mod)
    + return res
    +
    +# this function takes a dictionary of dependent modules and
    +# creates a list of lists. the first list will be modules
    +# that have no dependencies; the second list will be those
    +# modules that have the first list as dependencies; the
    +# third will be those modules that have the first and second...
    +# etc.
    +
    +
    +def make_deps(app_name, deps, mod_list):
    + print "Calculating Dependencies ..."
    + mod_list = filter_mods(app_name, mod_list)
    + deps = filter_deps(app_name, deps)
    +
    + if not mod_list:
    + return []
    +
    + #print mod_list
    + #print deps
    +
    + ordered_deps = []
    + last_len = -1
    + while deps:
    + l_deps = len(deps)
    + #print l_deps
    + if l_deps==last_len:
    + for m, dl in deps.items():
    + for d in dl:
    + if m in deps.get(d, []):
    + raise Exception('Circular Imports found: \n%s %s -> %s %s'
    + % (m, dl, d, deps[d]))
    + #raise Exception('Could not calculate dependencies: \n%s' % deps)
    + break
    + last_len = l_deps
    + #print "modlist", mod_list
    + nodeps = nodeps_list(mod_list, deps)
    + #print "nodeps", nodeps
    + mod_list = filter(lambda x: x not in nodeps, mod_list)
    + newdeps = {}
    + for k in deps.keys():
    + depslist = deps[k]
    + depslist = filter(lambda x: x not in nodeps, depslist)
    + if depslist:
    + newdeps[k] = depslist
    + #print "newdeps", newdeps
    + deps = newdeps
    + ordered_deps.append(nodeps)
    + #time.sleep(0)
    +
    + if mod_list:
    + ordered_deps.append(mod_list) # last dependencies - usually the app(s)
    +
    + ordered_deps.reverse()
    +
    + return ordered_deps
    +
    +def main():
    + global app_platforms
    +
    + parser = OptionParser(usage = usage, version = version)
    + parser.add_option("-o", "--output", dest="output",
    + help="directory to which the webapp should be written")
    + parser.add_option("-j", "--include-js", dest="js_includes", action="append",
    + help="javascripts to load into the same frame as the rest of the script")
    + parser.add_option("-I", "--library_dir", dest="library_dirs",
    + action="append", help="additional paths appended to PYJSPATH")
    + parser.add_option("-D", "--data_dir", dest="data_dir",
    + help="path for data directory")
    + parser.add_option("-m", "--dynamic-modules", action="store_true",
    + dest="dynamic", default=False,
    + help="Split output into separate dynamically-loaded modules (experimental)")
    + parser.add_option("-P", "--platforms", dest="platforms",
    + help="platforms to build for, comma-separated")
    + parser.add_option("-d", "--debug", action="store_true", dest="debug")
    + parser.add_option("-O", "--optimize", action="store_true",
    + dest="optimize", default=False,
    + help="Optimize generated code (removes all print statements)",
    + )
    + parser.add_option("-c", "--cache_buster", action="store_true",
    + dest="cache_buster",
    + help="Enable browser cache-busting (MD5 hash added to output filenames)")
    +
    + parser.set_defaults(output = "output", js_includes=[], library_dirs=[],
    + platforms=(','.join(app_platforms)),
    + data_dir=os.path.join(sys.prefix, "share/pyjamas"),
    + dynamic=False,
    + cache_buster=False,
    + debug=False)
    + (options, args) = parser.parse_args()
    + if len(args) != 1:
    + parser.error("incorrect number of arguments")
    +
    + data_dir = abspath(options.data_dir)
    +
    + app_path = args[0]
    + if app_path.endswith('.py'):
    + app_path = abspath(app_path)
    + if not isfile(app_path):
    + parser.error("Application file not found %r" % app_path)
    + app_path, app_name = split(app_path)
    + app_name = app_name[:-3]
    + pyjs.path.append(app_path)
    + elif os.path.sep in app_path:
    + parser.error("Not a valid module declaration %r" % app_path)
    + else:
    + app_name = app_path
    +
    + for d in options.library_dirs:
    + pyjs.path.append(abspath(d))
    +
    + if options.platforms:
    + app_platforms = options.platforms.split(',')
    +
    + # this is mostly for getting boilerplate stuff
    + data_dir = os.path.abspath(options.data_dir)
    +
    + build(app_name, options.output, options.js_includes,
    + options.debug, options.dynamic and 1 or 0, data_dir,
    + options.cache_buster, options.optimize)
    +
    +if __name__ == "__main__":
    + main()
    +
    --- /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 @@
    +# jsonrpc.py
    +# original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas
    +# also from: http://www.pimentech.fr/technologies/outils
    +from django.utils import simplejson
    +from django.http import HttpResponse
    +import sys
    +
    +from pyjs.jsonrpc import JSONRPCServiceBase
    +# JSONRPCService and jsonremote are used in combination to drastically
    +# simplify the provision of JSONRPC services. use as follows:
    +#
    +# jsonservice = JSONRPCService()
    +#
    +# @jsonremote(jsonservice)
    +# def test(request, echo_param):
    +# return "echoing the param back: %s" % echo_param
    +#
    +# dump jsonservice into urlpatterns:
    +# (r'^service1/$', 'djangoapp.views.jsonservice'),
    +
    +class JSONRPCService(JSONRPCServiceBase):
    +
    + def __call__(self, request, extra=None):
    + return self.process(request.raw_post_data)
    +
    +def jsonremote(service):
    + """Make JSONRPCService a decorator so that you can write :
    +
    + from jsonrpc import JSONRPCService
    + chatservice = JSONRPCService()
    +
    + @jsonremote(chatservice)
    + def login(request, user_name):
    + (...)
    + """
    + def remotify(func):
    + if isinstance(service, JSONRPCService):
    + service.add_method(func.__name__, func)
    + else:
    + emsg = 'Service "%s" not found' % str(service.__name__)
    + raise NotImplementedError, emsg
    + return func
    + return remotify
    +
    +
    +# FormProcessor provides a mechanism for turning Django Forms into JSONRPC
    +# Services. If you have an existing Django app which makes prevalent
    +# use of Django Forms it will save you rewriting the app.
    +# use as follows. in djangoapp/views.py :
    +#
    +# class SimpleForm(forms.Form):
    +# testfield = forms.CharField(max_length=100)
    +#
    +# class SimpleForm2(forms.Form):
    +# testfield = forms.CharField(max_length=20)
    +#
    +# processor = FormProcessor({'processsimpleform': SimpleForm,
    +# 'processsimpleform2': SimpleForm2})
    +#
    +# this will result in a JSONRPC service being created with two
    +# RPC functions. dump "processor" into urlpatterns to make it
    +# part of the app:
    +# (r'^formsservice/$', 'djangoapp.views.processor'),
    +
    +from django import forms
    +
    +def builderrors(form):
    + d = {}
    + for error in form.errors.keys():
    + if error not in d:
    + d[error] = []
    + for errorval in form.errors[error]:
    + d[error].append(unicode(errorval))
    + return d
    +
    +
    +# contains the list of arguments in each field
    +field_names = {
    + 'CharField': ['max_length', 'min_length'],
    + 'IntegerField': ['max_value', 'min_value'],
    + 'FloatField': ['max_value', 'min_value'],
    + 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'],
    + 'DateField': ['input_formats'],
    + 'DateTimeField': ['input_formats'],
    + 'TimeField': ['input_formats'],
    + 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr
    + 'EmailField': ['max_length', 'min_length'],
    + 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'],
    + 'ChoiceField': ['choices'],
    + 'FilePathField': ['path', 'match', 'recursive', 'choices'],
    + 'IPAddressField': ['max_length', 'min_length'],
    + }
    +
    +def describe_field_errors(field):
    + res = {}
    + field_type = field.__class__.__name__
    + msgs = {}
    + for n, m in field.error_messages.items():
    + msgs[n] = unicode(m)
    + res['error_messages'] = msgs
    + if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
    + res['fields'] = map(describe_field, field.fields)
    + return res
    +
    +def describe_fields_errors(fields, field_names):
    + res = {}
    + if not field_names:
    + field_names = fields.keys()
    + for name in field_names:
    + field = fields[name]
    + res[name] = describe_field_errors(field)
    + return res
    +
    +def describe_field(field):
    + res = {}
    + field_type = field.__class__.__name__
    + for fname in field_names.get(field_type, []) + \
    + ['help_text', 'label', 'initial', 'required']:
    + res[fname] = getattr(field, fname)
    + if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
    + res['fields'] = map(describe_field, field.fields)
    + return res
    +
    +def describe_fields(fields, field_names):
    + res = {}
    + if not field_names:
    + field_names = fields.keys()
    + for name in field_names:
    + field = fields[name]
    + res[name] = describe_field(field)
    + return res
    +
    +class FormProcessor(JSONRPCService):
    + def __init__(self, forms, _formcls=None):
    +
    + if _formcls is None:
    + JSONRPCService.__init__(self)
    + for k in forms.keys():
    + s = FormProcessor({}, forms[k])
    + self.add_method(k, s.__process)
    + else:
    + JSONRPCService.__init__(self, forms)
    + self.formcls = _formcls
    +
    + def __process(self, request, params, command=None):
    +
    + f = self.formcls(params)
    +
    + if command is None: # just validate
    + if not f.is_valid():
    + return {'success':False, 'errors': builderrors(f)}
    + return {'success':True}
    +
    + elif command.has_key('describe_errors'):
    + field_names = command['describe_errors']
    + return describe_fields_errors(f.fields, field_names)
    +
    + elif command.has_key('describe'):
    + field_names = command['describe']
    + return describe_fields(f.fields, field_names)
    +
    + elif command.has_key('save'):
    + if not f.is_valid():
    + return {'success':False, 'errors': builderrors(f)}
    + instance = f.save() # XXX: if you want more, over-ride save.
    + return {'success': True, 'instance': json_convert(instance) }
    +
    + elif command.has_key('html'):
    + return {'success': True, 'html': f.as_table()}
    +
    + return "unrecognised command"
    +
    +
    +
    +
    +# The following is incredibly convenient for saving vast amounts of
    +# coding, avoiding doing silly things like this:
    +# jsonresult = {'field1': djangoobject.field1,
    +# 'field2': djangoobject.date.strftime('%Y.%M'),
    +# ..... }
    +#
    +# The date/time flatten function is there because JSONRPC doesn't
    +# support date/time objects or formats, so conversion to a string
    +# is the most logical choice. pyjamas, being python, can easily
    +# be used to parse the string result at the other end.
    +#
    +# use as follows:
    +#
    +# jsonservice = JSONRPCService()
    +#
    +# @jsonremote(jsonservice)
    +# def list_some_model(request, start=0, count=10):
    +# l = SomeDjangoModelClass.objects.filter()
    +# res = json_convert(l[start:end])
    +#
    +# @jsonremote(jsonservice)
    +# def list_another_model(request, start=0, count=10):
    +# l = AnotherDjangoModelClass.objects.filter()
    +# res = json_convert(l[start:end])
    +#
    +# dump jsonservice into urlpatterns to make the two RPC functions,
    +# list_some_model and list_another_model part of the django app:
    +# (r'^service1/$', 'djangoapp.views.jsonservice'),
    +
    +from django.core.serializers import serialize
    +import datetime
    +from datetime import date
    +
    +def dict_datetimeflatten(item):
    + d = {}
    + for k, v in item.items():
    + k = str(k)
    + if isinstance(v, datetime.date):
    + d[k] = str(v)
    + elif isinstance(v, dict):
    + d[k] = dict_datetimeflatten(v)
    + else:
    + d[k] = v
    + return d
    +
    +def json_convert(l, fields=None):
    + res = []
    + for item in serialize('python', l, fields=fields):
    + res.append(dict_datetimeflatten(item))
    + return res
    +
    --- /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
    +import types
    +import sys
    +
    +class JSONRPCServiceBase:
    +
    + def __init__(self):
    + self.methods={}
    +
    + def response(self, id, result):
    + return simplejson.dumps({'version': '1.1', 'id':id,
    + 'result':result, 'error':None})
    + def error(self, id, code, message):
    + return simplejson.dumps({'id': id,
    + 'version': '1.1',
    + 'error': {'name': 'JSONRPCError',
    + 'code': code,
    + 'message': message
    + }
    + })
    +
    + def add_method(self, name, method):
    + self.methods[name] = method
    +
    + def process(self, data):
    + data = simplejson.loads(data)
    + id, method, params = data["id"], data["method"], data["params"]
    + if method in self.methods:
    + try:
    + result =self.methods[method](*params)
    + return self.response(id, result)
    + except BaseException:
    + etype, eval, etb = sys.exc_info()
    + return self.error(id, 100, '%s: %s' %(etype.__name__, eval))
    + except:
    + etype, eval, etb = sys.exc_info()
    + return self.error(id, 100, 'Exception %s: %s' %(etype, eval))
    + else:
    + return self.error(id, 100, 'method "%s" does not exist' % method)
    +
    + def listmethods(self):
    + return self.methods.keys()
    +
    --- /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):
    +
    + def serve(self):
    + return self.process(request.body.read())
    +
    + def __call__(self,func):
    + self.methods[func.__name__]=func
    + return 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))
    + {
    + klass_object[i] = v;
    + }
    + }
    +
    + function klass_inherit() {}
    + klass_inherit.prototype = klass_object;
    + klass.prototype = new klass_inherit();
    + klass_object.constructor = klass;
    + klass.prototype.__class__ = klass_object;
    +
    + for (var i in base.prototype) {
    + v = base.prototype[i];
    + if (typeof v == "function" && v.instance_method)
    + {
    + klass.prototype[i] = v;
    + }
    + }
    +}
    +
    +/* creates a class, derived from bases, with methods and variables */
    +function pyjs_type(clsname, bases, methods)
    +{
    + var fn_cls = function() {};
    + fn_cls.__name__ = clsname;
    + var fn = function() {
    + var instance = new fn_cls();
    + if(instance.__init__) instance.__init__.apply(instance, arguments);
    + return instance;
    + }
    + fn_cls.__initialize__ = function() {
    + if (fn_cls.__was_initialized__) return;
    + fn_cls.__was_initialized__ = true;
    + fn_cls.__extend_baseclasses();
    + fn_cls.prototype.__class__.__new__ = fn;
    + fn_cls.prototype.__class__.__name__ = clsname;
    + }
    + fn_cls.__extend_baseclasses = function() {
    + var bi;
    + for (bi in fn_cls.__baseclasses)
    + {
    + var b = fn_cls.__baseclasses[bi];
    + if (b.__was_initialized__)
    + {
    + continue;
    + }
    + b.__initialize__();
    + }
    + for (bi in fn_cls.__baseclasses)
    + {
    + var b = fn_cls.__baseclasses[bi];
    + pyjs_extend(fn_cls, b);
    + }
    + }
    + if (!bases) {
    + bases = [pyjslib.__Object];
    + }
    + fn_cls.__baseclasses = bases;
    +
    + fn_cls.__initialize__();
    +
    + for (k in methods) {
    + var mth = methods[k];
    + var mtype = typeof mth;
    + if (mtype == "function" ) {
    + fn_cls.prototype[k] = mth;
    + fn_cls.prototype.__class__[k] = function () {
    + return fn_cls.prototype[k].call.apply(
    + fn_cls.prototype[k], arguments);
    + };
    + fn_cls.prototype.__class__[k].unbound_method = true;
    + fn_cls.prototype.instance_method = true;
    + fn_cls.prototype.__class__[k].__name__ = k;
    + fn_cls.prototype[k].__name__ = k;
    + } else {
    + fn_cls.prototype.__class__[k] = mth;
    + }
    + }
    + return fn;
    +}
    +function pyjs_kwargs_call(obj, func, star_args, args)
    +{
    + var call_args;
    +
    + if (star_args)
    + {
    + if (!pyjslib.isIteratable(star_args))
    + {
    + throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args)));
    + }
    + call_args = Array();
    + var __i = star_args.__iter__();
    + var i = 0;
    + try {
    + while (true) {
    + call_args[i]=__i.next();
    + i++;
    + }
    + } catch (e) {
    + if (e != pyjslib.StopIteration) {
    + throw e;
    + }
    + }
    +
    + if (args)
    + {
    + var n = star_args.length;
    + for (var i=0; i < args.length; i++) {
    + call_args[n+i]=args[i];
    + }
    + }
    + }
    + else
    + {
    + call_args = args;
    + }
    + return func.apply(obj, call_args);
    +}
    +
    +function pyjs_kwargs_function_call(func, star_args, args)
    +{
    + return pyjs_kwargs_call(null, func, star_args, args);
    +}
    +
    +function pyjs_kwargs_method_call(obj, method_name, star_args, args)
    +{
    + var method = obj[method_name];
    + if (method.parse_kwargs)
    + {
    + args = method.parse_kwargs.apply(null, args);
    + }
    + return pyjs_kwargs_call(obj, method, star_args, args);
    +}
    +
    +//String.prototype.__getitem__ = String.prototype.charAt;
    +//String.prototype.upper = String.prototype.toUpperCase;
    +//String.prototype.lower = String.prototype.toLowerCase;
    +//String.prototype.find=pyjslib.String_find;
    +//String.prototype.join=pyjslib.String_join;
    +//String.prototype.isdigit=pyjslib.String_isdigit;
    +//String.prototype.__iter__=pyjslib.String___iter__;
    +//
    +//String.prototype.__replace=String.prototype.replace;
    +//String.prototype.replace=pyjslib.String_replace;
    +//
    +//String.prototype.split=pyjslib.String_split;
    +//String.prototype.strip=pyjslib.String_strip;
    +//String.prototype.lstrip=pyjslib.String_lstrip;
    +//String.prototype.rstrip=pyjslib.String_rstrip;
    +//String.prototype.startswith=pyjslib.String_startswith;
    +
    +var str = String;
    +
    --- /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
    +// global variables.
    +
    + var at, // The index of the current character
    + ch, // The current character
    + escapee = {
    + '"': '"',
    + '\\': '\\',
    + '/': '/',
    + b: '\b',
    + f: '\f',
    + n: '\n',
    + r: '\r',
    + t: '\t'
    + },
    + text,
    +
    + error = function (m) {
    +
    +// Call error when something is wrong.
    +
    + throw {
    + name: 'SyntaxError',
    + message: m,
    + at: at,
    + text: text
    + };
    + },
    +
    + next = function (c) {
    +
    +// If a c parameter is provided, verify that it matches the current character.
    +
    + if (c && c !== ch) {
    + error("Expected '" + c + "' instead of '" + ch + "'");
    + }
    +
    +// Get the next character. When there are no more characters,
    +// return the empty string.
    +
    + ch = text.charAt(at);
    + at += 1;
    + return ch;
    + },
    +
    + number = function () {
    +
    +// Parse a number value.
    +
    + var number,
    + string = '';
    +
    + if (ch === '-') {
    + string = '-';
    + next('-');
    + }
    + while (ch >= '0' && ch <= '9') {
    + string += ch;
    + next();
    + }
    + if (ch === '.') {
    + string += '.';
    + while (next() && ch >= '0' && ch <= '9') {
    + string += ch;
    + }
    + }
    + if (ch === 'e' || ch === 'E') {
    + string += ch;
    + next();
    + if (ch === '-' || ch === '+') {
    + string += ch;
    + next();
    + }
    + while (ch >= '0' && ch <= '9') {
    + string += ch;
    + next();
    + }
    + }
    + number = +string;
    + if (isNaN(number)) {
    + error("Bad number");
    + } else {
    + return number;
    + }
    + },
    +
    + string = function () {
    +
    +// Parse a string value.
    +
    + var hex,
    + i,
    + string = '',
    + uffff;
    +
    +// When parsing for string values, we must look for " and \ characters.
    +
    + if (ch === '"') {
    + while (next()) {
    + if (ch === '"') {
    + next();
    + return string;
    + } else if (ch === '\\') {
    + next();
    + if (ch === 'u') {
    + uffff = 0;
    + for (i = 0; i < 4; i += 1) {
    + hex = parseInt(next(), 16);
    + if (!isFinite(hex)) {
    + break;
    + }
    + uffff = uffff * 16 + hex;
    + }
    + string += String.fromCharCode(uffff);
    + } else if (typeof escapee[ch] === 'string') {
    + string += escapee[ch];
    + } else {
    + break;
    + }
    + } else {
    + string += ch;
    + }
    + }
    + }
    + error("Bad string");
    + },
    +
    + white = function () {
    +
    +// Skip whitespace.
    +
    + while (ch && ch <= ' ') {
    + next();
    + }
    + },
    +
    + word = function () {
    +
    +// true, false, or null.
    +
    + switch (ch) {
    + case 't':
    + next('t');
    + next('r');
    + next('u');
    + next('e');
    + return true;
    + case 'f':
    + next('f');
    + next('a');
    + next('l');
    + next('s');
    + next('e');
    + return false;
    + case 'n':
    + next('n');
    + next('u');
    + next('l');
    + next('l');
    + return null;
    + }
    + error("Unexpected '" + ch + "'");
    + },
    +
    + value, // Place holder for the value function.
    +
    + array = function () {
    +
    +// Parse an array value.
    +
    + var array = [];
    +
    + if (ch === '[') {
    + next('[');
    + white();
    + if (ch === ']') {
    + next(']');
    + return array; // empty array
    + }
    + while (ch) {
    + array.push(value());
    + white();
    + if (ch === ']') {
    + next(']');
    + return array;
    + }
    + next(',');
    + white();
    + }
    + }
    + error("Bad array");
    + },
    +
    + object = function () {
    +
    +// Parse an object value.
    +
    + var key,
    + object = {};
    +
    + if (ch === '{') {
    + next('{');
    + white();
    + if (ch === '}') {
    + next('}');
    + return object; // empty object
    + }
    + while (ch) {
    + key = string();
    + white();
    + next(':');
    + if (Object.hasOwnProperty.call(object, key)) {
    + error('Duplicate key "' + key + '"');
    + }
    + object[key] = value();
    + white();
    + if (ch === '}') {
    + next('}');
    + return object;
    + }
    + next(',');
    + white();
    + }
    + }
    + error("Bad object");
    + };
    +
    + value = function () {
    +
    +// Parse a JSON value. It could be an object, an array, a string, a number,
    +// or a word.
    +
    + white();
    + switch (ch) {
    + case '{':
    + return object();
    + case '[':
    + return array();
    + case '"':
    + return string();
    + case '-':
    + return number();
    + default:
    + return ch >= '0' && ch <= '9' ? number() : word();
    + }
    + };
    +
    +// Return the json_parse function. It will have access to all of the above
    +// functions and variables.
    +
    + return function (source, reviver) {
    + var result;
    +
    + text = source;
    + at = 0;
    + ch = ' ';
    + result = value();
    + white();
    + if (ch) {
    + error("Syntax error");
    + }
    +
    +// If there is a reviver function, we recursively walk the new structure,
    +// passing each name/value pair to the reviver function for possible
    +// transformation, starting with a temporary root object that holds the result
    +// in an empty key. If there is not a reviver function, we simply return the
    +// result.
    +
    + return typeof reviver === 'function' ? (function walk(holder, key) {
    + var k, v, value = holder[key];
    + if (value && typeof value === 'object') {
    + for (k in value) {
    + if (Object.hasOwnProperty.call(value, k)) {
    + v = walk(value, k);
    + if (v !== undefined) {
    + value[k] = v;
    + } else {
    + delete value[k];
    + }
    + }
    + }
    + }
    + return reviver.call(holder, key, value);
    + }({'': result}, '')) : result;
    + };
    +}());
    --- /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):
    + """
    + """
    +
    + JS("""
    + var cache_file;
    +
    + if (module_name == "sys" || module_name == 'pyjslib')
    + {
    + /*module_load_request[module_name] = 1;*/
    + return;
    + }
    +
    + if (path == null)
    + {
    + path = './';
    + }
    +
    + var override_name = sys.platform + "." + module_name;
    + if (((sys.overrides != null) &&
    + (sys.overrides.has_key(override_name))))
    + {
    + cache_file = sys.overrides.__getitem__(override_name) ;
    + }
    + else
    + {
    + cache_file = module_name ;
    + }
    +
    + cache_file = (path + cache_file + '.cache.js' ) ;
    +
    + //alert("cache " + cache_file + " " + module_name + " " + parent_module);
    +
    + /* already loaded? */
    + if (module_load_request[module_name])
    + {
    + if (module_load_request[module_name] >= 3 && parent_module != null)
    + {
    + //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';';
    + //pyjs_eval(onload_fn); /* set up the parent-module namespace */
    + }
    + return;
    + }
    + if (typeof (module_load_request[module_name]) == 'undefined')
    + {
    + module_load_request[module_name] = 1;
    + }
    +
    + /* following a load, this first executes the script
    + * "preparation" function MODULENAME_loaded_fn()
    + * and then sets up the loaded module in the namespace
    + * of the parent.
    + */
    +
    + onload_fn = ''; // module_name + "_loaded_fn();"
    +
    + if (parent_module != null)
    + {
    + //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';';
    + /*pmod = parent_module + '.' + module_name;
    + onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/
    + }
    +
    +
    + if (dynamic)
    + {
    + /* this one tacks the script onto the end of the DOM
    + */
    +
    + pyjs_load_script(cache_file, onload_fn, async);
    +
    + /* this one actually RUNS the script (eval) into the page.
    + my feeling is that this would be better for non-async
    + but i can't get it to work entirely yet.
    + */
    + /*pyjs_ajax_eval(cache_file, onload_fn, async);*/
    + }
    + else
    + {
    + if (module_name != "pyjslib" &&
    + module_name != "sys")
    + pyjs_eval(onload_fn);
    + }
    +
    + """)
    +
    +JS("""
    +function import_wait(proceed_fn, parent_mod, dynamic) {
    +
    + var data = '';
    + var element = $doc.createElement("div");
    + $doc.body.appendChild(element);
    + function write_dom(txt) {
    + element.innerHTML = txt + '<br />';
    + }
    +
    + var timeoutperiod = 1;
    + if (dynamic)
    + var timeoutperiod = 1;
    +
    + var wait = function() {
    +
    + var status = '';
    + for (l in module_load_request)
    + {
    + var m = module_load_request[l];
    + if (l == "sys" || l == 'pyjslib')
    + continue;
    + status += l + m + " ";
    + }
    +
    + //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
    + wait_count += 1;
    +
    + if (status == '')
    + {
    + setTimeout(wait, timeoutperiod);
    + return;
    + }
    +
    + for (l in module_load_request)
    + {
    + var m = module_load_request[l];
    + if (l == "sys" || l == 'pyjslib')
    + {
    + module_load_request[l] = 4;
    + continue;
    + }
    + if ((parent_mod != null) && (l == parent_mod))
    + {
    + if (m == 1)
    + {
    + setTimeout(wait, timeoutperiod);
    + return;
    + }
    + if (m == 2)
    + {
    + /* cheat and move app on to next stage */
    + module_load_request[l] = 3;
    + }
    + }
    + if (m == 1 || m == 2)
    + {
    + setTimeout(wait, timeoutperiod);
    + return;
    + }
    + if (m == 3)
    + {
    + //alert("waited for module " + l + ": loaded");
    + module_load_request[l] = 4;
    + mod_fn = modules[l];
    + }
    + }
    + //alert("module wait done");
    +
    + if (proceed_fn.importDone)
    + proceed_fn.importDone(proceed_fn);
    + else
    + proceed_fn();
    + }
    +
    + wait();
    +}
    +""")
    +
    +class Object:
    + pass
    +
    +object = Object
    +
    +class Modload:
    +
    + def __init__(self, path, app_modlist, app_imported_fn, dynamic,
    + parent_mod):
    + self.app_modlist = app_modlist
    + self.app_imported_fn = app_imported_fn
    + self.path = path
    + self.idx = 0;
    + self.dynamic = dynamic
    + self.parent_mod = parent_mod
    +
    + def next(self):
    +
    + for i in range(len(self.app_modlist[self.idx])):
    + app = self.app_modlist[self.idx][i]
    + import_module(self.path, self.parent_mod, app, self.dynamic, True);
    + self.idx += 1
    +
    + if self.idx >= len(self.app_modlist):
    + import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
    + else:
    + import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
    +
    +def get_module(module_name):
    + ev = "__mod = %s;" % module_name
    + JS("pyjs_eval(ev);")
    + return __mod
    +
    +def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
    + parent_mod=None):
    +
    + loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
    + loader.next()
    +
    +import sys
    +
    +class BaseException:
    +
    + name = "BaseException"
    +
    + def __init__(self, *args):
    + self.args = args
    +
    + def __str__(self):
    + if len(self.args) is 0:
    + return ''
    + elif len(self.args) is 1:
    + return repr(self.args[0])
    + return repr(self.args)
    +
    + def toString(self):
    + return str(self)
    +
    +class Exception(BaseException):
    +
    + name = "Exception"
    +
    +class TypeError(BaseException):
    + name = "TypeError"
    +
    +class StandardError(Exception):
    + name = "StandardError"
    +
    +class LookupError(StandardError):
    + name = "LookupError"
    +
    + def toString(self):
    + return self.name + ": " + self.args[0]
    +
    +class KeyError(LookupError):
    + name = "KeyError"
    +
    +class AttributeError(StandardError):
    +
    + name = "AttributeError"
    +
    + def toString(self):
    + return "AttributeError: %s of %s" % (self.args[1], self.args[0])
    +
    +JS("""
    +pyjslib.StopIteration = function () { };
    +pyjslib.StopIteration.prototype = new Error();
    +pyjslib.StopIteration.name = 'StopIteration';
    +pyjslib.StopIteration.message = 'StopIteration';
    +
    +pyjslib.String_find = function(sub, start, end) {
    + var pos=this.indexOf(sub, start);
    + if (pyjslib.isUndefined(end)) return pos;
    +
    + if (pos + sub.length>end) return -1;
    + return pos;
    +}
    +
    +pyjslib.String_join = function(data) {
    + var text="";
    +
    + if (pyjslib.isArray(data)) {
    + return data.join(this);
    + }
    + else if (pyjslib.isIteratable(data)) {
    + var iter=data.__iter__();
    + try {
    + text+=iter.next();
    + while (true) {
    + var item=iter.next();
    + text+=this + item;
    + }
    + }
    + catch (e) {
    + if (e != pyjslib.StopIteration) throw e;
    + }
    + }
    +
    + return text;
    +}
    +
    +pyjslib.String_isdigit = function() {
    + return (this.match(/^\d+$/g) != null);
    +}
    +
    +pyjslib.String_replace = function(old, replace, count) {
    + var do_max=false;
    + var start=0;
    + var new_str="";
    + var pos=0;
    +
    + if (!pyjslib.isString(old)) return this.__replace(old, replace);
    + if (!pyjslib.isUndefined(count)) do_max=true;
    +
    + while (start<this.length) {
    + if (do_max && !count--) break;
    +
    + pos=this.indexOf(old, start);
    + if (pos<0) break;
    +
    + new_str+=this.substring(start, pos) + replace;
    + start=pos+old.length;
    + }
    + if (start<this.length) new_str+=this.substring(start);
    +
    + return new_str;
    +}
    +
    +pyjslib.String_split = function(sep, maxsplit) {
    + var items=new pyjslib.List();
    + var do_max=false;
    + var subject=this;
    + var start=0;
    + var pos=0;
    +
    + if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) {
    + sep=" ";
    + subject=subject.strip();
    + subject=subject.replace(/\s+/g, sep);
    + }
    + else if (!pyjslib.isUndefined(maxsplit)) do_max=true;
    +
    + if (subject.length == 0) {
    + return items;
    + }
    +
    + while (start<subject.length) {
    + if (do_max && !maxsplit--) break;
    +
    + pos=subject.indexOf(sep, start);
    + if (pos<0) break;
    +
    + items.append(subject.substring(start, pos));
    + start=pos+sep.length;
    + }
    + if (start<=subject.length) items.append(subject.substring(start));
    +
    + return items;
    +}
    +
    +pyjslib.String___iter__ = function() {
    + var i = 0;
    + var s = this;
    + return {
    + 'next': function() {
    + if (i >= s.length) {
    + throw pyjslib.StopIteration;
    + }
    + return s.substring(i++, i, 1);
    + },
    + '__iter__': function() {
    + return this;
    + }
    + };
    +}
    +
    +pyjslib.String_strip = function(chars) {
    + return this.lstrip(chars).rstrip(chars);
    +}
    +
    +pyjslib.String_lstrip = function(chars) {
    + if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, "");
    +
    + return this.replace(new RegExp("^[" + chars + "]+"), "");
    +}
    +
    +pyjslib.String_rstrip = function(chars) {
    + if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, "");
    +
    + return this.replace(new RegExp("[" + chars + "]+$"), "");
    +}
    +
    +pyjslib.String_startswith = function(prefix, start) {
    + if (pyjslib.isUndefined(start)) start = 0;
    +
    + if (this.substring(start, prefix.length) == prefix) return true;
    + return false;
    +}
    +
    +pyjslib.abs = Math.abs;
    +
    +""")
    +
    +class Class:
    + def __init__(self, name):
    + self.name = name
    +
    + def __str___(self):
    + return self.name
    +
    +def eq(a,b):
    + JS("""
    + if (pyjslib.hasattr(a, "__cmp__")) {
    + return a.__cmp__(b) == 0;
    + } else if (pyjslib.hasattr(b, "__cmp__")) {
    + return b.__cmp__(a) == 0;
    + }
    + return a == b;
    + """)
    +
    +def cmp(a,b):
    + if hasattr(a, "__cmp__"):
    + return a.__cmp__(b)
    + elif hasattr(b, "__cmp__"):
    + return -b.__cmp__(a)
    + if a > b:
    + return 1
    + elif b > a:
    + return -1
    + else:
    + return 0
    +
    +def bool(v):
    + # this needs to stay in native code without any dependencies here,
    + # because this is used by if and while, we need to prevent
    + # recursion
    + JS("""
    + if (!v) return false;
    + switch(typeof v){
    + case 'boolean':
    + return v;
    + case 'object':
    + if (v.__nonzero__){
    + return v.__nonzero__();
    + }else if (v.__len__){
    + return v.__len__()>0;
    + }
    + return true;
    + }
    + return Boolean(v);
    + """)
    +
    +class List:
    + def __init__(self, data=None):
    + JS("""
    + this.l = [];
    + this.extend(data);
    + """)
    +
    + def append(self, item):
    + JS(""" this.l[this.l.length] = item;""")
    +
    + def extend(self, data):
    + JS("""
    + if (pyjslib.isArray(data)) {
    + n = this.l.length;
    + for (var i=0; i < data.length; i++) {
    + this.l[n+i]=data[i];
    + }
    + }
    + else if (pyjslib.isIteratable(data)) {
    + var iter=data.__iter__();
    + var i=this.l.length;
    + try {
    + while (true) {
    + var item=iter.next();
    + this.l[i++]=item;
    + }
    + }
    + catch (e) {
    + if (e != pyjslib.StopIteration) throw e;
    + }
    + }
    + """)
    +
    + def remove(self, value):
    + JS("""
    + var index=this.index(value);
    + if (index<0) return false;
    + this.l.splice(index, 1);
    + return true;
    + """)
    +
    + def index(self, value, start=0):
    + JS("""
    + var length=this.l.length;
    + for (var i=start; i<length; i++) {
    + if (this.l[i]==value) {
    + return i;
    + }
    + }
    + return -1;
    + """)
    +
    + 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):
    + JS("""
    + if (index<0) index = this.l.length + index;
    + var a = this.l[index];
    + this.l.splice(index, 1);
    + return a;
    + """)
    +
    + def __cmp__(self, l):
    + if not isinstance(l, List):
    + return -1
    + ll = len(self) - len(l)
    + if ll != 0:
    + return ll
    + for x in range(len(l)):
    + ll = cmp(self.__getitem__(x), l[x])
    + if ll != 0:
    + return ll
    + return 0
    +
    + def slice(self, lower, upper):
    + JS("""
    + if (upper==null) return pyjslib.List(this.l.slice(lower));
    + return pyjslib.List(this.l.slice(lower, upper));
    + """)
    +
    + def __getitem__(self, index):
    + JS("""
    + if (index<0) index = this.l.length + index;
    + return this.l[index];
    + """)
    +
    + def __setitem__(self, index, value):
    + JS(""" this.l[index]=value;""")
    +
    + def __delitem__(self, index):
    + JS(""" this.l.splice(index, 1);""")
    +
    + def __len__(self):
    + JS(""" return this.l.length;""")
    +
    + def __contains__(self, value):
    + return self.index(value) >= 0
    +
    + def __iter__(self):
    + JS("""
    + var i = 0;
    + var l = this.l;
    + return {
    + 'next': function() {
    + if (i >= l.length) {
    + throw pyjslib.StopIteration;
    + }
    + return l[i++];
    + },
    + '__iter__': function() {
    + return this;
    + }
    + };
    + """)
    +
    + def reverse(self):
    + JS(""" this.l.reverse();""")
    +
    + def sort(self, compareFunc=None, keyFunc=None, reverse=False):
    + if not compareFunc:
    + global cmp
    + compareFunc = cmp
    + if keyFunc and reverse:
    + def thisSort1(a,b):
    + return -compareFunc(keyFunc(a), keyFunc(b))
    + self.l.sort(thisSort1)
    + elif keyFunc:
    + def thisSort2(a,b):
    + return compareFunc(keyFunc(a), keyFunc(b))
    + self.l.sort(thisSort2)
    + elif reverse:
    + def thisSort3(a,b):
    + return -compareFunc(a, b)
    + self.l.sort(thisSort3)
    + else:
    + self.l.sort(compareFunc)
    +
    + def getArray(self):
    + """
    + Access the javascript Array that is used internally by this list
    + """
    + return self.l
    +
    + def __str__(self):
    + return repr(self)
    +
    +list = List
    +
    +class Tuple:
    + def __init__(self, data=None):
    + JS("""
    + this.l = [];
    + this.extend(data);
    + """)
    +
    + def append(self, item):
    + JS(""" this.l[this.l.length] = item;""")
    +
    + def extend(self, data):
    + JS("""
    + if (pyjslib.isArray(data)) {
    + n = this.l.length;
    + for (var i=0; i < data.length; i++) {
    + this.l[n+i]=data[i];
    + }
    + }
    + else if (pyjslib.isIteratable(data)) {
    + var iter=data.__iter__();
    + var i=this.l.length;
    + try {
    + while (true) {
    + var item=iter.next();
    + this.l[i++]=item;
    + }
    + }
    + catch (e) {
    + if (e != pyjslib.StopIteration) throw e;
    + }
    + }
    + """)
    +
    + def remove(self, value):
    + JS("""
    + var index=this.index(value);
    + if (index<0) return false;
    + this.l.splice(index, 1);
    + return true;
    + """)
    +
    + def index(self, value, start=0):
    + JS("""
    + var length=this.l.length;
    + for (var i=start; i<length; i++) {
    + if (this.l[i]==value) {
    + return i;
    + }
    + }
    + return -1;
    + """)
    +
    + 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):
    + JS("""
    + if (index<0) index = this.l.length + index;
    + var a = this.l[index];
    + this.l.splice(index, 1);
    + return a;
    + """)
    +
    + def __cmp__(self, l):
    + if not isinstance(l, Tuple):
    + return -1
    + ll = len(self) - len(l)
    + if ll != 0:
    + return ll
    + for x in range(len(l)):
    + ll = cmp(self.__getitem__(x), l[x])
    + if ll != 0:
    + return ll
    + return 0
    +
    + def slice(self, lower, upper):
    + JS("""
    + if (upper==null) return pyjslib.Tuple(this.l.slice(lower));
    + return pyjslib.Tuple(this.l.slice(lower, upper));
    + """)
    +
    + def __getitem__(self, index):
    + JS("""
    + if (index<0) index = this.l.length + index;
    + return this.l[index];
    + """)
    +
    + def __setitem__(self, index, value):
    + JS(""" this.l[index]=value;""")
    +
    + def __delitem__(self, index):
    + JS(""" this.l.splice(index, 1);""")
    +
    + def __len__(self):
    + JS(""" return this.l.length;""")
    +
    + def __contains__(self, value):
    + return self.index(value) >= 0
    +
    + def __iter__(self):
    + JS("""
    + var i = 0;
    + var l = this.l;
    + return {
    + 'next': function() {
    + if (i >= l.length) {
    + throw pyjslib.StopIteration;
    + }
    + return l[i++];
    + },
    + '__iter__': function() {
    + return this;
    + }
    + };
    + """)
    +
    + def reverse(self):
    + JS(""" this.l.reverse();""")
    +
    + def sort(self, compareFunc=None, keyFunc=None, reverse=False):
    + if not compareFunc:
    + global cmp
    + compareFunc = cmp
    + if keyFunc and reverse:
    + def thisSort1(a,b):
    + return -compareFunc(keyFunc(a), keyFunc(b))
    + self.l.sort(thisSort1)
    + elif keyFunc:
    + def thisSort2(a,b):
    + return compareFunc(keyFunc(a), keyFunc(b))
    + self.l.sort(thisSort2)
    + elif reverse:
    + def thisSort3(a,b):
    + return -compareFunc(a, b)
    + self.l.sort(thisSort3)
    + else:
    + self.l.sort(compareFunc)
    +
    + def getArray(self):
    + """
    + Access the javascript Array that is used internally by this list
    + """
    + return self.l
    +
    + def __str__(self):
    + return repr(self)
    +
    +tuple = Tuple
    +
    +
    +class Dict:
    + def __init__(self, data=None):
    + JS("""
    + this.d = {};
    +
    + if (pyjslib.isArray(data)) {
    + for (var i in data) {
    + var item=data[i];
    + this.__setitem__(item[0], item[1]);
    + //var sKey=pyjslib.hash(item[0]);
    + //this.d[sKey]=item[1];
    + }
    + }
    + else if (pyjslib.isIteratable(data)) {
    + var iter=data.__iter__();
    + try {
    + while (true) {
    + var item=iter.next();
    + this.__setitem__(item.__getitem__(0), item.__getitem__(1));
    + }
    + }
    + catch (e) {
    + if (e != pyjslib.StopIteration) throw e;
    + }
    + }
    + else if (pyjslib.isObject(data)) {
    + for (var key in data) {
    + this.__setitem__(key, data[key]);
    + }
    + }
    + """)
    +
    + def __setitem__(self, key, value):
    + JS("""
    + var sKey = pyjslib.hash(key);
    + this.d[sKey]=[key, value];
    + """)
    +
    + def __getitem__(self, key):
    + JS("""
    + var sKey = pyjslib.hash(key);
    + var value=this.d[sKey];
    + if (pyjslib.isUndefined(value)){
    + throw pyjslib.KeyError(key);
    + }
    + return value[1];
    + """)
    +
    + def __nonzero__(self):
    + JS("""
    + for (var i in this.d){
    + return true;
    + }
    + return false;
    + """)
    +
    + def __len__(self):
    + JS("""
    + var size=0;
    + for (var i in this.d) size++;
    + return size;
    + """)
    +
    + def has_key(self, key):
    + return self.__contains__(key)
    +
    + def __delitem__(self, key):
    + JS("""
    + var sKey = pyjslib.hash(key);
    + delete this.d[sKey];
    + """)
    +
    + def __contains__(self, key):
    + JS("""
    + var sKey = pyjslib.hash(key);
    + return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
    + """)
    +
    + def keys(self):
    + JS("""
    + var keys=new pyjslib.List();
    + for (var key in this.d) {
    + keys.append(this.d[key][0]);
    + }
    + return keys;
    + """)
    +
    + def values(self):
    + JS("""
    + var values=new pyjslib.List();
    + for (var key in this.d) values.append(this.d[key][1]);
    + return values;
    + """)
    +
    + def items(self):
    + JS("""
    + var items = new pyjslib.List();
    + for (var key in this.d) {
    + var kv = this.d[key];
    + items.append(new pyjslib.List(kv))
    + }
    + return items;
    + """)
    +
    + def __iter__(self):
    + return self.keys().__iter__()
    +
    + def iterkeys(self):
    + return self.__iter__()
    +
    + def itervalues(self):
    + return self.values().__iter__();
    +
    + def iteritems(self):
    + return self.items().__iter__();
    +
    + def setdefault(self, key, default_value):
    + if not self.has_key(key):
    + self[key] = default_value
    +
    + def get(self, key, default_=None):
    + if not self.has_key(key):
    + return default_
    + return self[key]
    +
    + def update(self, d):
    + for k,v in d.iteritems():
    + self[k] = v
    +
    + def getObject(self):
    + """
    + Return the javascript Object which this class uses to store
    + dictionary keys and values
    + """
    + return self.d
    +
    + def copy(self):
    + return Dict(self.items())
    +
    + def __str__(self):
    + return repr(self)
    +
    +dict = Dict
    +
    +# taken from mochikit: range( [start,] stop[, step] )
    +def range():
    + JS("""
    + var start = 0;
    + var stop = 0;
    + var step = 1;
    +
    + if (arguments.length == 2) {
    + start = arguments[0];
    + stop = arguments[1];
    + }
    + else if (arguments.length == 3) {
    + start = arguments[0];
    + stop = arguments[1];
    + step = arguments[2];
    + }
    + else if (arguments.length>0) stop = arguments[0];
    +
    + return {
    + 'next': function() {
    + if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
    + var rval = start;
    + start += step;
    + return rval;
    + },
    + '__iter__': function() {
    + return this;
    + }
    + }
    + """)
    +
    +def slice(object, lower, upper):
    + JS("""
    + if (pyjslib.isString(object)) {
    + if (lower < 0) {
    + lower = object.length + lower;
    + }
    + if (upper < 0) {
    + upper = object.length + upper;
    + }
    + if (pyjslib.isNull(upper)) upper=object.length;
    + return object.substring(lower, upper);
    + }
    + if (pyjslib.isObject(object) && object.slice)
    + return object.slice(lower, upper);
    +
    + return null;
    + """)
    +
    +def str(text):
    + JS("""
    + if (pyjslib.hasattr(text,"__str__")) {
    + return text.__str__();
    + }
    + return String(text);
    + """)
    +
    +def ord(x):
    + if(isString(x) and len(x) is 1):
    + JS("""
    + return x.charCodeAt(0);
    + """)
    + else:
    + JS("""
    + throw pyjslib.TypeError();
    + """)
    + return None
    +
    +def chr(x):
    + JS("""
    + return String.fromCharCode(x)
    + """)
    +
    +def is_basetype(x):
    + JS("""
    + var t = typeof(x);
    + return t == 'boolean' ||
    + t == 'function' ||
    + t == 'number' ||
    + t == 'string' ||
    + t == 'undefined'
    + ;
    + """)
    +
    +def get_pyjs_classtype(x):
    + JS("""
    + if (pyjslib.hasattr(x, "__class__"))
    + if (pyjslib.hasattr(x.__class__, "__new__"))
    + var src = x.__class__.__name__;
    + return src;
    + return null;
    + """)
    +
    +def repr(x):
    + """ Return the string representation of 'x'.
    + """
    + JS("""
    + if (x === null)
    + return "null";
    +
    + if (x === undefined)
    + return "undefined";
    +
    + var t = typeof(x);
    +
    + //alert("repr typeof " + t + " : " + x);
    +
    + if (t == "boolean")
    + return x.toString();
    +
    + if (t == "function")
    + return "<function " + x.toString() + ">";
    +
    + if (t == "number")
    + return x.toString();
    +
    + if (t == "string") {
    + if (x.indexOf("'") == -1)
    + return "'" + x + "'";
    + if (x.indexOf('"') == -1)
    + return '"' + x + '"';
    + var s = x.replace(new RegExp('"', "g"), '\\\\"');
    + return '"' + s + '"';
    + };
    +
    + if (t == "undefined")
    + return "undefined";
    +
    + // If we get here, x is an object. See if it's a Pyjamas class.
    +
    + if (!pyjslib.hasattr(x, "__init__"))
    + return "<" + x.toString() + ">";
    +
    + // Handle the common Pyjamas data types.
    +
    + var constructor = "UNKNOWN";
    +
    + constructor = pyjslib.get_pyjs_classtype(x);
    +
    + //alert("repr constructor: " + constructor);
    +
    + if (constructor == "Tuple") {
    + var contents = x.getArray();
    + var s = "(";
    + for (var i=0; i < contents.length; i++) {
    + s += pyjslib.repr(contents[i]);
    + if (i < contents.length - 1)
    + s += ", ";
    + };
    + s += ")"
    + return s;
    + };
    +
    + if (constructor == "List") {
    + var contents = x.getArray();
    + var s = "[";
    + for (var i=0; i < contents.length; i++) {
    + s += pyjslib.repr(contents[i]);
    + if (i < contents.length - 1)
    + s += ", ";
    + };
    + s += "]"
    + return s;
    + };
    +
    + if (constructor == "Dict") {
    + var keys = new Array();
    + for (var key in x.d)
    + keys.push(key);
    +
    + var s = "{";
    + for (var i=0; i<keys.length; i++) {
    + var key = keys[i]
    + s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]);
    + if (i < keys.length-1)
    + s += ", "
    + };
    + s += "}";
    + return s;
    + };
    +
    + // 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>";
    + """)
    +
    +def float(text):
    + JS("""
    + return parseFloat(text);
    + """)
    +
    +def int(text, radix=0):
    + JS("""
    + return parseInt(text, radix);
    + """)
    +
    +def len(object):
    + JS("""
    + if (object==null) return 0;
    + if (pyjslib.isObject(object) && object.__len__) return object.__len__();
    + return object.length;
    + """)
    +
    +def isinstance(object_, classinfo):
    + if pyjslib.isUndefined(object_):
    + return False
    + if not pyjslib.isObject(object_):
    +
    + return False
    + if _isinstance(classinfo, Tuple):
    + for ci in classinfo:
    + if isinstance(object_, ci):
    + return True
    + return False
    + else:
    + return _isinstance(object_, classinfo)
    +
    +def _isinstance(object_, classinfo):
    + if not pyjslib.isObject(object_):
    + return False
    + JS("""
    + if (object_.__class__){
    + var res = object_ instanceof classinfo.constructor;
    + return res;
    + }
    + return false;
    + """)
    +
    +def getattr(obj, name, default_):
    + JS("""
    + if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
    + if (pyjslib.isUndefined(default_)){
    + throw pyjslib.AttributeError(obj, name);
    + }else{
    + return default_;
    + }
    + }
    + if (!pyjslib.isFunction(obj[name])) return obj[name];
    + var fnwrap = function() {
    + var args = [];
    + for (var i = 0; i < arguments.length; i++) {
    + args.push(arguments[i]);
    + }
    + return obj[name].apply(obj,args);
    + }
    + fnwrap.__name__ = name;
    + return fnwrap;
    + """)
    +
    +def setattr(obj, name, value):
    + JS("""
    + if (!pyjslib.isObject(obj)) return null;
    +
    + obj[name] = value;
    +
    + """)
    +
    +def hasattr(obj, name):
    + JS("""
    + if (!pyjslib.isObject(obj)) return false;
    + if (pyjslib.isUndefined(obj[name])) return false;
    +
    + return true;
    + """)
    +
    +def dir(obj):
    + JS("""
    + var properties=new pyjslib.List();
    + for (property in obj) properties.append(property);
    + return properties;
    + """)
    +
    +def filter(obj, method, sequence=None):
    + # object context is LOST when a method is passed, hence object must be passed separately
    + # to emulate python behaviour, should generate this code inline rather than as a function call
    + items = []
    + if sequence is None:
    + sequence = method
    + method = obj
    +
    + for item in sequence:
    + if method(item):
    + items.append(item)
    + else:
    + for item in sequence:
    + if method.call(obj, item):
    + items.append(item)
    +
    + return items
    +
    +
    +def map(obj, method, sequence=None):
    + items = []
    +
    + if sequence is None:
    + sequence = method
    + method = obj
    +
    + for item in sequence:
    + items.append(method(item))
    + else:
    + for item in sequence:
    + items.append(method.call(obj, item))
    +
    + return items
    +
    +
    +def enumerate(sequence):
    + enumeration = []
    + nextIndex = 0
    + for item in sequence:
    + enumeration.append([nextIndex, item])
    + nextIndex = nextIndex + 1
    + return enumeration
    +
    +
    +def min(*sequence):
    + minValue = None
    + for item in sequence:
    + if minValue is None:
    + minValue = item
    + elif item < minValue:
    + minValue = item
    + return minValue
    +
    +
    +def max(*sequence):
    + maxValue = None
    + for item in sequence:
    + if maxValue is None:
    + maxValue = item
    + elif item > maxValue:
    + maxValue = item
    + return maxValue
    +
    +
    +next_hash_id = 0
    +
    +def hash(obj):
    + JS("""
    + if (obj == null) return null;
    +
    + if (obj.$H) return obj.$H;
    + if (obj.__hash__) return obj.__hash__();
    + if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
    +
    + obj.$H = ++pyjslib.next_hash_id;
    + return obj.$H;
    + """)
    +
    +
    +# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
    +def isObject(a):
    + JS("""
    + return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
    + """)
    +
    +def isFunction(a):
    + JS("""
    + return typeof a == 'function';
    + """)
    +
    +def isString(a):
    + JS("""
    + return typeof a == 'string';
    + """)
    +
    +def isNull(a):
    + JS("""
    + return typeof a == 'object' && !a;
    + """)
    +
    +def isArray(a):
    + JS("""
    + return pyjslib.isObject(a) && a.constructor == Array;
    + """)
    +
    +def isUndefined(a):
    + JS("""
    + return typeof a == 'undefined';
    + """)
    +
    +def isIteratable(a):
    + JS("""
    + return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
    + """)
    +
    +def isNumber(a):
    + JS("""
    + return typeof a == 'number' && isFinite(a);
    + """)
    +
    +def toJSObjects(x):
    + """
    + Convert the pyjs pythonic List and Dict objects into javascript Object and Array
    + objects, recursively.
    + """
    + if isArray(x):
    + JS("""
    + var result = [];
    + for(var k=0; k < x.length; k++) {
    + var v = x[k];
    + var tv = pyjslib.toJSObjects(v);
    + result.push(tv);
    + }
    + return result;
    + """)
    + if isObject(x):
    + if isinstance(x, Dict):
    + JS("""
    + var o = x.getObject();
    + var result = {};
    + for (var i in o) {
    + result[o[i][0].toString()] = o[i][1];
    + }
    + return pyjslib.toJSObjects(result)
    + """)
    + elif isinstance(x, List):
    + return toJSObjects(x.l)
    + elif hasattr(x, '__class__'):
    + # we do not have a special implementation for custom
    + # classes, just pass it on
    + return x
    + if isObject(x):
    + JS("""
    + var result = {};
    + for(var k in x) {
    + var v = x[k];
    + var tv = pyjslib.toJSObjects(v)
    + result[k] = tv;
    + }
    + return result;
    + """)
    + return x
    +
    +def printFunc(objs):
    + JS("""
    + if ($wnd.console==undefined) return;
    + var s = "";
    + for(var i=0; i < objs.length; i++) {
    + if(s != "") s += " ";
    + s += objs[i];
    + }
    + console.debug(s)
    + """)
    +
    +def type(clsname, bases=None, methods=None):
    + """ creates a class, derived from bases, with methods and variables
    + """
    +
    + JS(" var mths = {}; ")
    + if methods:
    + for k in methods.keys():
    + mth = methods[k]
    + JS(" mths[k] = mth; ")
    +
    + JS(" var bss = null; ")
    + if bases:
    + JS("bss = bases.l;")
    + JS(" return pyjs_type(clsname, bss, mths); ")
    +
    --- /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
    +loadpath = None
    +
    +stacktrace = None
    +
    +appname = None
    +
    +def setloadpath(lp):
    + global loadpath
    + loadpath = lp
    +
    +def setappname(an):
    + global appname
    + appname = an
    +
    +def getloadpath():
    + global loadpath
    + return loadpath
    +
    +def addoverride(module_name, path):
    + global overrides
    + overrides[module_name] = path
    +
    +def addstack(linedebug):
    + JS("""
    + if (pyjslib.bool((sys.stacktrace === null))) {
    + sys.stacktrace = new pyjslib.List([]);
    + }
    + sys.stacktrace.append(linedebug);
    + """)
    +def popstack():
    + JS("""
    + sys.stacktrace.pop()
    + """)
    +
    +def printstack():
    + JS("""
    + var res = '';
    +
    + var __l = sys.stacktrace.__iter__();
    + try {
    + while (true) {
    + var l = __l.next();
    + res += ( l + '\\n' ) ;
    + }
    + } catch (e) {
    + if (e != pyjslib.StopIteration) {
    + throw e;
    + }
    + }
    +
    + return res;
    + """)
    --- /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 @@
    +#!/usr/bin/env python
    +# Copyright 2006 James Tauber and contributors
    +#
    +# Licensed under the Apache License, Version 2.0 (the "License");
    +# you may not use this file except in compliance with the License.
    +# You may obtain a copy of the License at
    +#
    +# http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +import sys
    +from types import StringType
    +import compiler
    +from compiler import ast
    +import os
    +import copy
    +
    +# the standard location for builtins (e.g. pyjslib) can be
    +# over-ridden by changing this. it defaults to sys.prefix
    +# so that on a system-wide install of pyjamas the builtins
    +# can be found in e.g. {sys.prefix}/share/pyjamas
    +#
    +# over-rides can be done by either explicitly modifying
    +# pyjs.prefix or by setting an environment variable, PYJSPREFIX.
    +
    +prefix = sys.prefix
    +
    +if os.environ.has_key('PYJSPREFIX'):
    + prefix = os.environ['PYJSPREFIX']
    +
    +# pyjs.path is the list of paths, just like sys.path, from which
    +# library modules will be searched for, for compile purposes.
    +# obviously we don't want to use sys.path because that would result
    +# in compiling standard python modules into javascript!
    +
    +path = [os.path.abspath('')]
    +
    +if os.environ.has_key('PYJSPATH'):
    + for p in os.environ['PYJSPATH'].split(os.pathsep):
    + p = os.path.abspath(p)
    + if os.path.isdir(p):
    + path.append(p)
    +
    +# this is the python function used to wrap native javascript
    +NATIVE_JS_FUNC_NAME = "JS"
    +
    +UU = ""
    +
    +PYJSLIB_BUILTIN_FUNCTIONS=("cmp",
    + "map",
    + "filter",
    + "dir",
    + "getattr",
    + "setattr",
    + "hasattr",
    + "int",
    + "float",
    + "str",
    + "repr",
    + "range",
    + "len",
    + "hash",
    + "abs",
    + "ord",
    + "chr",
    + "enumerate",
    + "min",
    + "max",
    + "bool",
    + "type",
    + "isinstance")
    +
    +PYJSLIB_BUILTIN_CLASSES=("BaseException",
    + "Exception",
    + "StandardError",
    + "StopIteration",
    + "AttributeError",
    + "TypeError",
    + "KeyError",
    + "LookupError",
    + "list",
    + "dict",
    + "object",
    + "tuple",
    + )
    +
    +def pyjs_builtin_remap(name):
    + # XXX HACK!
    + if name == 'list':
    + name = 'List'
    + if name == 'object':
    + name = '__Object'
    + if name == 'dict':
    + name = 'Dict'
    + if name == 'tuple':
    + name = 'Tuple'
    + return name
    +
    +# XXX: this is a hack: these should be dealt with another way
    +# however, console is currently the only global name which is causing
    +# problems.
    +PYJS_GLOBAL_VARS=("console")
    +
    +# This is taken from the django project.
    +# Escape every ASCII character with a value less than 32.
    +JS_ESCAPES = (
    + ('\\', r'\x5C'),
    + ('\'', r'\x27'),
    + ('"', r'\x22'),
    + ('>', r'\x3E'),
    + ('<', r'\x3C'),
    + ('&', r'\x26'),
    + (';', r'\x3B')
    + ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)])
    +
    +def escapejs(value):
    + """Hex encodes characters for use in JavaScript strings."""
    + for bad, good in JS_ESCAPES:
    + value = value.replace(bad, good)
    + return value
    +
    +def uuprefix(name, leave_alone=0):
    + name = name.split(".")
    + name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:])
    + return '.'.join(name)
    +
    +class Klass:
    +
    + klasses = {}
    +
    + def __init__(self, name, name_):
    + self.name = name
    + self.name_ = name_
    + self.klasses[name] = self
    + self.functions = set()
    +
    + def set_base(self, base_name):
    + self.base = self.klasses.get(base_name)
    +
    + def add_function(self, function_name):
    + self.functions.add(function_name)
    +
    +
    +class TranslationError(Exception):
    + def __init__(self, message, node):
    + self.message = "line %s:\n%s\n%s" % (node.lineno, message, node)
    +
    + def __str__(self):
    + return self.message
    +
    +def strip_py(name):
    + return name
    +
    +def mod_var_name_decl(raw_module_name):
    + """ function to get the last component of the module e.g.
    + pyjamas.ui.DOM into the "namespace". i.e. doing
    + "import pyjamas.ui.DOM" actually ends up with _two_
    + variables - one pyjamas.ui.DOM, the other just "DOM".
    + but "DOM" is actually local, hence the "var" prefix.
    +
    + for PyV8, this might end up causing problems - we'll have
    + to see: gen_mod_import and mod_var_name_decl might have
    + to end up in a library-specific module, somewhere.
    + """
    + name = raw_module_name.split(".")
    + if len(name) == 1:
    + return ''
    + child_name = name[-1]
    + return "var %s = %s;\n" % (child_name, raw_module_name)
    +
    +def gen_mod_import(parentName, importName, dynamic=1):
    + #pyjs_ajax_eval("%(n)s.cache.js", null, true);
    + return """
    + pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false);
    + """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \
    + mod_var_name_decl(importName)
    +
    +class Translator:
    +
    + def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output,
    + dynamic=0, optimize=False,
    + findFile=None):
    +
    + if module_name:
    + self.module_prefix = module_name + "."
    + else:
    + self.module_prefix = ""
    + self.raw_module_name = raw_module_name
    + src = src.replace("\r\n", "\n")
    + src = src.replace("\n\r", "\n")
    + src = src.replace("\r", "\n")
    + self.src = src.split("\n")
    + self.debug = debug
    + self.imported_modules = []
    + self.imported_modules_as = []
    + self.imported_js = set()
    + self.top_level_functions = set()
    + self.top_level_classes = set()
    + self.top_level_vars = set()
    + self.local_arg_stack = [[]]
    + self.output = output
    + self.imported_classes = {}
    + self.method_imported_globals = set()
    + self.method_self = None
    + self.nextTupleAssignID = 1
    + self.dynamic = dynamic
    + self.optimize = optimize
    + self.findFile = findFile
    +
    + if module_name.find(".") >= 0:
    + vdec = ''
    + else:
    + vdec = 'var '
    + print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name)
    +
    + print >>self.output, " if("+module_name+".__was_initialized__) return;"
    + print >>self.output, " "+UU+module_name+".__was_initialized__ = true;"
    + print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn)
    + print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name)
    +
    + decl = mod_var_name_decl(raw_module_name)
    + if decl:
    + print >>self.output, decl
    +
    +
    + if self.debug:
    + haltException = self.module_prefix + "HaltException"
    + print >>self.output, haltException + ' = function () {'
    + print >>self.output, ' this.message = "Program Halted";'
    + print >>self.output, ' this.name = "' + haltException + '";'
    + print >>self.output, '}'
    + print >>self.output, ''
    + print >>self.output, haltException + ".prototype.__str__ = function()"
    + print >>self.output, '{'
    + print >>self.output, 'return this.message ;'
    + print >>self.output, '}'
    +
    + print >>self.output, haltException + ".prototype.toString = function()"
    + print >>self.output, '{'
    + print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";'
    + print >>self.output, '}'
    +
    + isHaltFunction = self.module_prefix + "IsHaltException"
    + print >>self.output, """
    + %s = function (s) {
    + var suffix="HaltException";
    + if (s.length < suffix.length) {
    + //alert(s + " " + suffix);
    + return false;
    + } else {
    + var ss = s.substring(s.length, (s.length - suffix.length));
    + //alert(s + " " + suffix + " " + ss);
    + return ss == suffix;
    + }
    + }
    + """ % isHaltFunction
    + for child in mod.node:
    + if isinstance(child, ast.Function):
    + self.top_level_functions.add(child.name)
    + elif isinstance(child, ast.Class):
    + self.top_level_classes.add(child.name)
    +
    + for child in mod.node:
    + if isinstance(child, ast.Function):
    + self._function(child, False)
    + elif isinstance(child, ast.Class):
    + self._class(child)
    + elif isinstance(child, ast.Import):
    + importName = child.names[0][0]
    + if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
    + pass
    + elif importName.endswith('.js'):
    + self.imported_js.add(importName)
    + else:
    + self.add_imported_module(strip_py(importName))
    + elif isinstance(child, ast.From):
    + if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
    + pass
    + else:
    + self.add_imported_module(child.modname)
    + self._from(child)
    + elif isinstance(child, ast.Discard):
    + self._discard(child, None)
    + elif isinstance(child, ast.Assign):
    + self._assign(child, None, True)
    + elif isinstance(child, ast.AugAssign):
    + self._augassign(child, None)
    + elif isinstance(child, ast.If):
    + self._if(child, None)
    + elif isinstance(child, ast.For):
    + self._for(child, None)
    + elif isinstance(child, ast.While):
    + self._while(child, None)
    + elif isinstance(child, ast.Subscript):
    + self._subscript_stmt(child, None)
    + elif isinstance(child, ast.Global):
    + self._global(child, None)
    + elif isinstance(child, ast.Printnl):
    + self._print(child, None)
    + elif isinstance(child, ast.Print):
    + self._print(child, None)
    + elif isinstance(child, ast.TryExcept):
    + self._tryExcept(child, None)
    + elif isinstance(child, ast.Raise):
    + self._raise(child, None)
    + elif isinstance(child, ast.Stmt):
    + self._stmt(child, None)
    + else:
    + raise TranslationError("unsupported type (in __init__)", child)
    +
    + # Initialize all classes for this module
    + #print >> self.output, "__"+self.modpfx()+\
    + # "classes_initialize = function() {\n"
    + #for className in self.top_level_classes:
    + # print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();"
    + #print >> self.output, "};\n"
    +
    + print >> self.output, "return this;\n"
    + print >> self.output, "}; /* end %s */ \n" % module_name
    +
    + def module_imports(self):
    + return self.imported_modules + self.imported_modules_as
    +
    + def add_local_arg(self, varname):
    + local_vars = self.local_arg_stack[-1]
    + if varname not in local_vars:
    + local_vars.append(varname)
    +
    + def add_imported_module(self, importName):
    +
    + if importName in self.imported_modules:
    + return
    + self.imported_modules.append(importName)
    + name = importName.split(".")
    + if len(name) != 1:
    + # add the name of the module to the namespace,
    + # but don't add the short name to imported_modules
    + # because then the short name would be attempted to be
    + # added to the dependencies, and it's half way up the
    + # module import directory structure!
    + child_name = name[-1]
    + self.imported_modules_as.append(child_name)
    + print >> self.output, gen_mod_import(self.raw_module_name,
    + strip_py(importName),
    + self.dynamic)
    +
    + def _default_args_handler(self, node, arg_names, current_klass,
    + output=None):
    + if len(node.defaults):
    + output = output or self.output
    + default_pos = len(arg_names) - len(node.defaults)
    + if arg_names and arg_names[0] == self.method_self:
    + default_pos -= 1
    + for default_node in node.defaults:
    + if isinstance(default_node, ast.Const):
    + default_value = self._const(default_node)
    + elif isinstance(default_node, ast.Name):
    + default_value = self._name(default_node, current_klass)
    + elif isinstance(default_node, ast.UnarySub):
    + default_value = self._unarysub(default_node, current_klass)
    + else:
    + raise TranslationError("unsupported type (in _method)", default_node)
    +
    + default_name = arg_names[default_pos]
    + default_pos += 1
    + print >> output, " if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value)
    +
    + def _varargs_handler(self, node, varargname, arg_names, current_klass):
    + print >>self.output, " var", varargname, '= new pyjslib.Tuple();'
    + print >>self.output, " for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {"
    + print >>self.output, " var __arg = arguments[__va_arg];"
    + print >>self.output, " "+varargname+".append(__arg);"
    + print >>self.output, " }"
    +
    + def _kwargs_parser(self, node, function_name, arg_names, current_klass):
    + if len(node.defaults) or node.kwargs:
    + default_pos = len(arg_names) - len(node.defaults)
    + if arg_names and arg_names[0] == self.method_self:
    + default_pos -= 1
    + print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {"
    + for default_node in node.defaults:
    + default_value = self.expr(default_node, current_klass)
    +# if isinstance(default_node, ast.Const):
    +# default_value = self._const(default_node)
    +# elif isinstance(default_node, ast.Name):
    +# default_value = self._name(default_node)
    +# elif isinstance(default_node, ast.UnarySub):
    +# default_value = self._unarysub(default_node, current_klass)
    +# else:
    +# raise TranslationError("unsupported type (in _method)", default_node)
    +
    + default_name = arg_names[default_pos]
    + print >>self.output, " if (typeof %s == 'undefined')"%(default_name)
    + print >>self.output, " %s=__kwargs.%s;"% (default_name, default_name)
    + default_pos += 1
    +
    + #self._default_args_handler(node, arg_names, current_klass)
    + if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"]
    + print >>self.output, " var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";"
    + if node.varargs:
    + self._varargs_handler(node, "__args", arg_names, current_klass)
    + print >>self.output, " __r.push.apply(__r, __args.getArray())"
    + print >>self.output, " return __r;"
    + print >>self.output, "};"
    +
    + def _function(self, node, local=False):
    + if local:
    + function_name = node.name
    + self.add_local_arg(function_name)
    + else:
    + function_name = UU + self.modpfx() + node.name
    +
    + arg_names = list(node.argnames)
    + normal_arg_names = list(arg_names)
    + if node.kwargs: kwargname = normal_arg_names.pop()
    + if node.varargs: varargname = normal_arg_names.pop()
    + declared_arg_names = list(normal_arg_names)
    + if node.kwargs: declared_arg_names.append(kwargname)
    +
    + function_args = "(" + ", ".join(declared_arg_names) + ")"
    + print >>self.output, "%s = function%s {" % (function_name, function_args)
    + self._default_args_handler(node, normal_arg_names, None)
    +
    + local_arg_names = normal_arg_names + declared_arg_names
    +
    + if node.varargs:
    + self._varargs_handler(node, varargname, declared_arg_names, None)
    + local_arg_names.append(varargname)
    +
    + # stack of local variable names for this function call
    + self.local_arg_stack.append(local_arg_names)
    +
    + for child in node.code:
    + self._stmt(child, None)
    +
    + # remove the top local arg names
    + self.local_arg_stack.pop()
    +
    + # we need to return null always, so it is not undefined
    + lastStmt = [p for p in node.code][-1]
    + if not isinstance(lastStmt, ast.Return):
    + if not self._isNativeFunc(lastStmt):
    + print >>self.output, " return null;"
    +
    + print >>self.output, "};"
    + print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name)
    +
    +
    + self._kwargs_parser(node, function_name, normal_arg_names, None)
    +
    +
    + def _return(self, node, current_klass):
    + expr = self.expr(node.value, current_klass)
    + # in python a function call always returns None, so we do it
    + # here too
    + print >>self.output, " return " + expr + ";"
    +
    +
    + def _break(self, node, current_klass):
    + print >>self.output, " break;"
    +
    +
    + def _continue(self, node, current_klass):
    + print >>self.output, " continue;"
    +
    +
    + def _callfunc(self, v, current_klass):
    +
    + if isinstance(v.node, ast.Name):
    + if v.node.name in self.top_level_functions:
    + call_name = self.modpfx() + v.node.name
    + elif v.node.name in self.top_level_classes:
    + call_name = self.modpfx() + v.node.name
    + elif self.imported_classes.has_key(v.node.name):
    + call_name = self.imported_classes[v.node.name] + '.' + v.node.name
    + elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS:
    + call_name = 'pyjslib.' + v.node.name
    + elif v.node.name in PYJSLIB_BUILTIN_CLASSES:
    + name = pyjs_builtin_remap(v.node.name)
    + call_name = 'pyjslib.' + name
    + elif v.node.name == "callable":
    + call_name = "pyjslib.isFunction"
    + else:
    + call_name = v.node.name
    + call_args = []
    + elif isinstance(v.node, ast.Getattr):
    + attr_name = v.node.attrname
    +
    + if isinstance(v.node.expr, ast.Name):
    + call_name = self._name2(v.node.expr, current_klass, attr_name)
    + call_args = []
    + elif isinstance(v.node.expr, ast.Getattr):
    + call_name = self._getattr2(v.node.expr, current_klass, attr_name)
    + call_args = []
    + elif isinstance(v.node.expr, ast.CallFunc):
    + call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname
    + call_args = []
    + elif isinstance(v.node.expr, ast.Subscript):
    + call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname
    + call_args = []
    + elif isinstance(v.node.expr, ast.Const):
    + call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname
    + call_args = []
    + else:
    + raise TranslationError("unsupported type (in _callfunc)", v.node.expr)
    + else:
    + raise TranslationError("unsupported type (in _callfunc)", v.node)
    +
    + call_name = strip_py(call_name)
    +
    + kwargs = []
    + star_arg_name = None
    + if v.star_args:
    + star_arg_name = self.expr(v.star_args, current_klass)
    +
    + for ch4 in v.args:
    + if isinstance(ch4, ast.Keyword):
    + kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass)
    + kwargs.append(kwarg)
    + else:
    + arg = self.expr(ch4, current_klass)
    + call_args.append(arg)
    +
    + if kwargs:
    + fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args)
    + else:
    + fn_args = ", ".join(call_args)
    +
    + if kwargs or star_arg_name:
    + if not star_arg_name:
    + star_arg_name = 'null'
    + try: call_this, method_name = call_name.rsplit(".", 1)
    + except ValueError:
    + # Must be a function call ...
    + return ("pyjs_kwargs_function_call("+call_name+", "
    + + star_arg_name
    + + ", ["+fn_args+"]"
    + + ")" )
    + else:
    + return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', "
    + + star_arg_name
    + + ", ["+fn_args+"]"
    + + ")")
    + else:
    + return call_name + "(" + ", ".join(call_args) + ")"
    +
    + def _print(self, node, current_klass):
    + if self.optimize:
    + return
    + call_args = []
    + for ch4 in node.nodes:
    + arg = self.expr(ch4, current_klass)
    + call_args.append(arg)
    +
    + print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");"
    +
    + def _tryExcept(self, node, current_klass):
    + if len(node.handlers) != 1:
    + raise TranslationError("except statements in this form are" +
    + " not supported", node)
    +
    + expr = node.handlers[0][0]
    + as_ = node.handlers[0][1]
    + if as_:
    + errName = as_.name
    + else:
    + errName = 'err'
    +
    + # XXX TODO: check that this should instead be added as a _separate_
    + # local scope, temporary to the function. oh dearie me.
    + self.add_local_arg(errName)
    +
    + print >>self.output, " try {"
    + for stmt in node.body.nodes:
    + self._stmt(stmt, current_klass)
    + print >> self.output, " } catch(%s) {" % errName
    + if expr:
    + l = []
    + if isinstance(expr, ast.Tuple):
    + for x in expr.nodes:
    + l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass)))
    + else:
    + l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ]
    + print >> self.output, " if(%s) {" % '||\n\t\t'.join(l)
    + for stmt in node.handlers[0][2]:
    + self._stmt(stmt, current_klass)
    + if expr:
    + #print >> self.output, "} else { throw(%s); } " % errName
    + print >> self.output, "}"
    + if node.else_ != None:
    + print >>self.output, " } finally {"
    + for stmt in node.else_:
    + self._stmt(stmt, current_klass)
    + print >>self.output, " }"
    +
    + # XXX: change use_getattr to True to enable "strict" compilation
    + # but incurring a 100% performance penalty. oops.
    + def _getattr(self, v, current_klass, use_getattr=False):
    + attr_name = v.attrname
    + if isinstance(v.expr, ast.Name):
    + obj = self._name(v.expr, current_klass, return_none_for_module=True)
    + if obj == None and v.expr.name in self.module_imports():
    + # XXX TODO: distinguish between module import classes
    + # and variables. right now, this is a hack to get
    + # the sys module working.
    + #if v.expr.name == 'sys':
    + return v.expr.name+'.'+attr_name
    + #return v.expr.name+'.__'+attr_name+'.prototype.__class__'
    + if not use_getattr or attr_name == '__class__' or \
    + attr_name == '__name__':
    + return obj + "." + attr_name
    + return "pyjslib.getattr(%s, '%s')" % (obj, attr_name)
    + elif isinstance(v.expr, ast.Getattr):
    + return self._getattr(v.expr, current_klass) + "." + attr_name
    + elif isinstance(v.expr, ast.Subscript):
    + return self._subscript(v.expr, self.modpfx()) + "." + attr_name
    + elif isinstance(v.expr, ast.CallFunc):
    + return self._callfunc(v.expr, self.modpfx()) + "." + attr_name
    + else:
    + raise TranslationError("unsupported type (in _getattr)", v.expr)
    +
    +
    + def modpfx(self):
    + return strip_py(self.module_prefix)
    +
    + def _name(self, v, current_klass, top_level=False,
    + return_none_for_module=False):
    +
    + if v.name == 'ilikesillynamesfornicedebugcode':
    + print top_level, current_klass, repr(v)
    + print self.top_level_vars
    + print self.top_level_functions
    + print self.local_arg_stack
    + print "error..."
    +
    + local_var_names = None
    + las = len(self.local_arg_stack)
    + if las > 0:
    + local_var_names = self.local_arg_stack[-1]
    +
    + if v.name == "True":
    + return "true"
    + elif v.name == "False":
    + return "false"
    + elif v.name == "None":
    + return "null"
    + elif v.name == '__name__' and current_klass is None:
    + return self.modpfx() + v.name
    + elif v.name == self.method_self:
    + return "this"
    + elif v.name in self.top_level_functions:
    + return UU+self.modpfx() + v.name
    + elif v.name in self.method_imported_globals:
    + return UU+self.modpfx() + v.name
    + elif not current_klass and las == 1 and v.name in self.top_level_vars:
    + return UU+self.modpfx() + v.name
    + elif v.name in local_var_names:
    + return v.name
    + elif self.imported_classes.has_key(v.name):
    + return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__"
    + elif v.name in self.top_level_classes:
    + return UU+self.modpfx() + "__" + v.name + ".prototype.__class__"
    + elif v.name in self.module_imports() and return_none_for_module:
    + return None
    + elif v.name in PYJSLIB_BUILTIN_CLASSES:
    + return "pyjslib." + pyjs_builtin_remap( v.name )
    + elif current_klass:
    + if v.name not in local_var_names and \
    + v.name not in self.top_level_vars and \
    + v.name not in PYJS_GLOBAL_VARS and \
    + v.name not in self.top_level_functions:
    +
    + cls_name = current_klass
    + if hasattr(cls_name, "name"):
    + cls_name_ = cls_name.name_
    + cls_name = cls_name.name
    + else:
    + cls_name_ = current_klass + "_" # XXX ???
    + name = UU+cls_name_ + ".prototype.__class__." \
    + + v.name
    + if v.name == 'listener':
    + name = 'listener+' + name
    + return name
    +
    + return v.name
    +
    + def _name2(self, v, current_klass, attr_name):
    + obj = v.name
    +
    + if obj in self.method_imported_globals:
    + call_name = UU+self.modpfx() + obj + "." + attr_name
    + elif self.imported_classes.has_key(obj):
    + #attr_str = ""
    + #if attr_name != "__init__":
    + attr_str = ".prototype.__class__." + attr_name
    + call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str
    + elif obj in self.module_imports():
    + call_name = obj + "." + attr_name
    + elif obj[0] == obj[0].upper(): # XXX HACK ALERT
    + call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name
    + else:
    + call_name = UU+self._name(v, current_klass) + "." + attr_name
    +
    + return call_name
    +
    +
    + def _getattr2(self, v, current_klass, attr_name):
    + if isinstance(v.expr, ast.Getattr):
    + call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name)
    + elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports():
    + call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name
    + else:
    + obj = self.expr(v.expr, current_klass)
    + call_name = obj + "." + v.attrname + "." + attr_name
    +
    + return call_name
    +
    +
    + def _class(self, node):
    + """
    + Handle a class definition.
    +
    + In order to translate python semantics reasonably well, the following
    + structure is used:
    +
    + A special object is created for the class, which inherits attributes
    + from the superclass, or Object if there's no superclass. This is the
    + class object; the object which you refer to when specifying the
    + class by name. Static, class, and unbound methods are copied
    + from the superclass object.
    +
    + A special constructor function is created with the same name as the
    + class, which is used to create instances of that class.
    +
    + A javascript class (e.g. a function with a prototype attribute) is
    + created which is the javascript class of created instances, and
    + which inherits attributes from the class object. Bound methods are
    + copied from the superclass into this class rather than inherited,
    + because the class object contains unbound, class, and static methods
    + that we don't necessarily want to inherit.
    +
    + The type of a method can now be determined by inspecting its
    + static_method, unbound_method, class_method, or instance_method
    + attribute; only one of these should be true.
    +
    + Much of this work is done in pyjs_extend, is pyjslib.py
    + """
    + class_name = self.modpfx() + uuprefix(node.name, 1)
    + class_name_ = self.modpfx() + uuprefix(node.name)
    + current_klass = Klass(class_name, class_name_)
    + init_method = None
    + for child in node.code:
    + if isinstance(child, ast.Function):
    + current_klass.add_function(child.name)
    + if child.name == "__init__":
    + init_method = child
    +
    +
    + if len(node.bases) == 0:
    + base_class = "pyjslib.__Object"
    + elif len(node.bases) == 1:
    + if isinstance(node.bases[0], ast.Name):
    + if self.imported_classes.has_key(node.bases[0].name):
    + base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name
    + base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name
    + else:
    + base_class_ = self.modpfx() + "__" + node.bases[0].name
    + base_class = self.modpfx() + node.bases[0].name
    + elif isinstance(node.bases[0], ast.Getattr):
    + # the bases are not in scope of the class so do not
    + # pass our class to self._name
    + base_class_ = self._name(node.bases[0].expr, None) + \
    + ".__" + node.bases[0].attrname
    + base_class = self._name(node.bases[0].expr, None) + \
    + "." + node.bases[0].attrname
    + else:
    + raise TranslationError("unsupported type (in _class)", node.bases[0])
    +
    + current_klass.set_base(base_class)
    + else:
    + raise TranslationError("more than one base (in _class)", node)
    +
    + print >>self.output, UU+class_name_ + " = function () {"
    + # call superconstructor
    + #if base_class:
    + # print >>self.output, " __" + base_class + ".call(this);"
    + print >>self.output, "}"
    +
    + if not init_method:
    + init_method = ast.Function([], "__init__", ["self"], [], 0, None, [])
    + #self._method(init_method, current_klass, class_name)
    +
    + # Generate a function which constructs the object
    + clsfunc = ast.Function([],
    + node.name,
    + init_method.argnames[1:],
    + init_method.defaults,
    + init_method.flags,
    + None,
    + [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const(
    +# I attempted lazy initialization, but then you can't access static class members
    +# " if(!__"+base_class+".__was_initialized__)"+
    +# " __" + class_name + "_initialize();\n" +
    + " var instance = new " + UU + class_name_ + "();\n" +
    + " if(instance.__init__) instance.__init__.apply(instance, arguments);\n" +
    + " return instance;"
    + )]))])
    +
    + self._function(clsfunc, False)
    + print >>self.output, UU+class_name_ + ".__initialize__ = function () {"
    + print >>self.output, " if("+UU+class_name_+".__was_initialized__) return;"
    + print >>self.output, " "+UU+class_name_+".__was_initialized__ = true;"
    + cls_obj = UU+class_name_ + '.prototype.__class__'
    +
    + if class_name == "pyjslib.__Object":
    + print >>self.output, " "+cls_obj+" = {};"
    + else:
    + if base_class and base_class not in ("object", "pyjslib.__Object"):
    + print >>self.output, " if(!"+UU+base_class_+".__was_initialized__)"
    + print >>self.output, " "+UU+base_class_+".__initialize__();"
    + print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");"
    + else:
    + print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);"
    +
    + print >>self.output, " "+cls_obj+".__new__ = "+UU+class_name+";"
    + print >>self.output, " "+cls_obj+".__name__ = '"+UU+node.name+"';"
    +
    + for child in node.code:
    + if isinstance(child, ast.Pass):
    + pass
    + elif isinstance(child, ast.Function):
    + self._method(child, current_klass, class_name, class_name_)
    + elif isinstance(child, ast.Assign):
    + self.classattr(child, current_klass)
    + elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const):
    + # Probably a docstring, turf it
    + pass
    + else:
    + raise TranslationError("unsupported type (in _class)", child)
    + print >>self.output, "}"
    +
    + print >> self.output, class_name_+".__initialize__();"
    +
    +
    + def classattr(self, node, current_klass):
    + self._assign(node, current_klass, True)
    +
    + def _raise(self, node, current_klass):
    + if node.expr2:
    + raise TranslationError("More than one expression unsupported",
    + node)
    + print >> self.output, "throw (%s);" % self.expr(
    + node.expr1, current_klass)
    +
    + def _method(self, node, current_klass, class_name, class_name_):
    + # reset global var scope
    + self.method_imported_globals = set()
    +
    + arg_names = list(node.argnames)
    +
    + classmethod = False
    + staticmethod = False
    + if node.decorators:
    + for d in node.decorators:
    + if d.name == "classmethod":
    + classmethod = True
    + elif d.name == "staticmethod":
    + staticmethod = True
    +
    + if staticmethod:
    + staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno)
    + self._function(staticfunc, True)
    + print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";";
    + print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;";
    + return
    + else:
    + if len(arg_names) == 0:
    + raise TranslationError("methods must take an argument 'self' (in _method)", node)
    + self.method_self = arg_names[0]
    +
    + #if not classmethod and arg_names[0] != "self":
    + # raise TranslationError("first arg not 'self' (in _method)", node)
    +
    + normal_arg_names = arg_names[1:]
    + if node.kwargs: kwargname = normal_arg_names.pop()
    + if node.varargs: varargname = normal_arg_names.pop()
    + declared_arg_names = list(normal_arg_names)
    + if node.kwargs: declared_arg_names.append(kwargname)
    +
    + function_args = "(" + ", ".join(declared_arg_names) + ")"
    +
    + if classmethod:
    + fexpr = UU + class_name_ + ".prototype.__class__." + node.name
    + else:
    + fexpr = UU + class_name_ + ".prototype." + node.name
    + print >>self.output, " "+fexpr + " = function" + function_args + " {"
    +
    + # default arguments
    + self._default_args_handler(node, normal_arg_names, current_klass)
    +
    + local_arg_names = normal_arg_names + declared_arg_names
    +
    + if node.varargs:
    + self._varargs_handler(node, varargname, declared_arg_names, current_klass)
    + local_arg_names.append(varargname)
    +
    +
    + # stack of local variable names for this function call
    + self.local_arg_stack.append(local_arg_names)
    +
    + for child in node.code:
    + self._stmt(child, current_klass)
    +
    + # remove the top local arg names
    + self.local_arg_stack.pop()
    +
    + print >>self.output, " };"
    +
    + self._kwargs_parser(node, fexpr, normal_arg_names, current_klass)
    +
    + if classmethod:
    + # Have to create a version on the instances which automatically passes the
    + # class as "self"
    + altexpr = UU + class_name_ + ".prototype." + node.name
    + print >>self.output, " "+altexpr + " = function() {"
    + print >>self.output, " return " + fexpr + ".apply(this.__class__, arguments);"
    + print >>self.output, " };"
    + print >>self.output, " "+fexpr+".class_method = true;"
    + print >>self.output, " "+altexpr+".instance_method = true;"
    + else:
    + # For instance methods, we need an unbound version in the class object
    + altexpr = UU + class_name_ + ".prototype.__class__." + node.name
    + print >>self.output, " "+altexpr + " = function() {"
    + print >>self.output, " return " + fexpr + ".call.apply("+fexpr+", arguments);"
    + print >>self.output, " };"
    + print >>self.output, " "+altexpr+".unbound_method = true;"
    + print >>self.output, " "+fexpr+".instance_method = true;"
    + print >>self.output, " "+altexpr+".__name__ = '%s';" % node.name
    +
    + print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \
    + (node.name, node.name)
    +
    + if node.kwargs or len(node.defaults):
    + print >>self.output, " "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;"
    +
    + self.method_self = None
    + self.method_imported_globals = set()
    +
    + def _isNativeFunc(self, node):
    + if isinstance(node, ast.Discard):
    + if isinstance(node.expr, ast.CallFunc):
    + if isinstance(node.expr.node, ast.Name) and \
    + node.expr.node.name == NATIVE_JS_FUNC_NAME:
    + return True
    + return False
    +
    + def _stmt(self, node, current_klass):
    + debugStmt = self.debug and not self._isNativeFunc(node)
    + if debugStmt:
    + print >>self.output, ' try {'
    +
    + if isinstance(node, ast.Return):
    + self._return(node, current_klass)
    + elif isinstance(node, ast.Break):
    + self._break(node, current_klass)
    + elif isinstance(node, ast.Continue):
    + self._continue(node, current_klass)
    + elif isinstance(node, ast.Assign):
    + self._assign(node, current_klass)
    + elif isinstance(node, ast.AugAssign):
    + self._augassign(node, current_klass)
    + elif isinstance(node, ast.Discard):
    + self._discard(node, current_klass)
    + elif isinstance(node, ast.If):
    + self._if(node, current_klass)
    + elif isinstance(node, ast.For):
    + self._for(node, current_klass)
    + elif isinstance(node, ast.While):
    + self._while(node, current_klass)
    + elif isinstance(node, ast.Subscript):
    + self._subscript_stmt(node, current_klass)
    + elif isinstance(node, ast.Global):
    + self._global(node, current_klass)
    + elif isinstance(node, ast.Pass):
    + pass
    + elif isinstance(node, ast.Function):
    + self._function(node, True)
    + elif isinstance(node, ast.Printnl):
    + self._print(node, current_klass)
    + elif isinstance(node, ast.Print):
    + self._print(node, current_klass)
    + elif isinstance(node, ast.TryExcept):
    + self._tryExcept(node, current_klass)
    + elif isinstance(node, ast.Raise):
    + self._raise(node, current_klass)
    + else:
    + raise TranslationError("unsupported type (in _stmt)", node)
    +
    + if debugStmt:
    +
    + lt = self.get_line_trace(node)
    +
    + haltException = self.module_prefix + "HaltException"
    + isHaltFunction = self.module_prefix + "IsHaltException"
    +
    + print >>self.output, ' } catch (__err) {'
    + print >>self.output, ' if (' + isHaltFunction + '(__err.name)) {'
    + print >>self.output, ' throw __err;'
    + print >>self.output, ' } else {'
    + print >>self.output, " st = sys.printstack() + "\
    + + '"%s"' % lt + "+ '\\n' ;"
    + print >>self.output, ' alert("' + "Error in " \
    + + lt + '"' \
    + + '+"\\n"+__err.name+": "+__err.message'\
    + + '+"\\n\\nStack trace:\\n"' \
    + + '+st' \
    + + ');'
    + print >>self.output, ' debugger;'
    +
    + print >>self.output, ' throw new ' + self.module_prefix + "HaltException();"
    + print >>self.output, ' }'
    + print >>self.output, ' }'
    +
    +
    + def get_line_trace(self, node):
    + lineNum = "Unknown"
    + srcLine = ""
    + if hasattr(node, "lineno"):
    + if node.lineno != None:
    + lineNum = node.lineno
    + srcLine = self.src[min(lineNum, len(self.src))-1]
    + srcLine = srcLine.replace('\\', '\\\\')
    + srcLine = srcLine.replace('"', '\\"')
    + srcLine = srcLine.replace("'", "\\'")
    +
    + return self.raw_module_name + ".py, line " \
    + + str(lineNum) + ":"\
    + + "\\n" \
    + + " " + srcLine
    +
    + def _augassign(self, node, current_klass):
    + v = node.node
    + if isinstance(v, ast.Getattr):
    + # XXX HACK! don't allow += on return result of getattr.
    + # TODO: create a temporary variable or something.
    + lhs = self._getattr(v, current_klass, False)
    + else:
    + lhs = self._name(node.node, current_klass)
    + op = node.op
    + rhs = self.expr(node.expr, current_klass)
    + print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
    +
    +
    + def _assign(self, node, current_klass, top_level = False):
    + if len(node.nodes) != 1:
    + tempvar = '__temp'+str(node.lineno)
    + tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno)
    + self._assign(tnode, current_klass, top_level)
    + for v in node.nodes:
    + tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno)
    + self._assign(tnode2, current_klass, top_level)
    + return
    +
    + local_var_names = None
    + if len(self.local_arg_stack) > 0:
    + local_var_names = self.local_arg_stack[-1]
    +
    + def _lhsFromAttr(v, current_klass):
    + attr_name = v.attrname
    + if isinstance(v.expr, ast.Name):
    + obj = v.expr.name
    + lhs = self._name(v.expr, current_klass) + "." + attr_name
    + elif isinstance(v.expr, ast.Getattr):
    + lhs = self._getattr(v, current_klass)
    + elif isinstance(v.expr, ast.Subscript):
    + lhs = self._subscript(v.expr, current_klass) + "." + attr_name
    + else:
    + raise TranslationError("unsupported type (in _assign)", v.expr)
    + return lhs
    +
    + def _lhsFromName(v, top_level, current_klass):
    + if top_level:
    + if current_klass:
    + lhs = UU+current_klass.name_ + ".prototype.__class__." \
    + + v.name
    + else:
    + self.top_level_vars.add(v.name)
    + vname = self.modpfx() + v.name
    + if not self.modpfx() and v.name not in\
    + self.method_imported_globals:
    + lhs = "var " + vname
    + else:
    + lhs = UU + vname
    + self.add_local_arg(v.name)
    + else:
    + if v.name in local_var_names:
    + lhs = v.name
    + elif v.name in self.method_imported_globals:
    + lhs = self.modpfx() + v.name
    + else:
    + lhs = "var " + v.name
    + self.add_local_arg(v.name)
    + return lhs
    +
    + dbg = 0
    + v = node.nodes[0]
    + if isinstance(v, ast.AssAttr):
    + lhs = _lhsFromAttr(v, current_klass)
    + if v.flags == "OP_ASSIGN":
    + op = "="
    + else:
    + raise TranslationError("unsupported flag (in _assign)", v)
    +
    + elif isinstance(v, ast.AssName):
    + lhs = _lhsFromName(v, top_level, current_klass)
    + if v.flags == "OP_ASSIGN":
    + op = "="
    + else:
    + raise TranslationError("unsupported flag (in _assign)", v)
    + elif isinstance(v, ast.Subscript):
    + if v.flags == "OP_ASSIGN":
    + obj = self.expr(v.expr, current_klass)
    + if len(v.subs) != 1:
    + raise TranslationError("must have one sub (in _assign)", v)
    + idx = self.expr(v.subs[0], current_klass)
    + value = self.expr(node.expr, current_klass)
    + print >>self.output, " " + obj + ".__setitem__(" + idx + ", " + value + ");"
    + return
    + else:
    + raise TranslationError("unsupported flag (in _assign)", v)
    + elif isinstance(v, (ast.AssList, ast.AssTuple)):
    + uniqueID = self.nextTupleAssignID
    + self.nextTupleAssignID += 1
    + tempName = "__tupleassign" + str(uniqueID) + "__"
    + print >>self.output, " var " + tempName + " = " + \
    + self.expr(node.expr, current_klass) + ";"
    + for index,child in enumerate(v.getChildNodes()):
    + rhs = tempName + ".__getitem__(" + str(index) + ")"
    +
    + if isinstance(child, ast.AssAttr):
    + lhs = _lhsFromAttr(child, current_klass)
    + elif isinstance(child, ast.AssName):
    + lhs = _lhsFromName(child, top_level, current_klass)
    + elif isinstance(child, ast.Subscript):
    + if child.flags == "OP_ASSIGN":
    + obj = self.expr(child.expr, current_klass)
    + if len(child.subs) != 1:
    + raise TranslationError("must have one sub " +
    + "(in _assign)", child)
    + idx = self.expr(child.subs[0], current_klass)
    + value = self.expr(node.expr, current_klass)
    + print >>self.output, " " + obj + ".__setitem__(" \
    + + idx + ", " + rhs + ");"
    + continue
    + print >>self.output, " " + lhs + " = " + rhs + ";"
    + return
    + else:
    + raise TranslationError("unsupported type (in _assign)", v)
    +
    + rhs = self.expr(node.expr, current_klass)
    + if dbg:
    + print "b", repr(node.expr), rhs
    + print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
    +
    +
    + def _discard(self, node, current_klass):
    +
    + if isinstance(node.expr, ast.CallFunc):
    + debugStmt = self.debug and not self._isNativeFunc(node)
    + if debugStmt and isinstance(node.expr.node, ast.Name) and \
    + node.expr.node.name == 'import_wait':
    + debugStmt = False
    + if debugStmt:
    + st = self.get_line_trace(node)
    + print >>self.output, "sys.addstack('%s');\n" % st
    + if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME:
    + if len(node.expr.args) != 1:
    + raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr)
    + if not isinstance(node.expr.args[0], ast.Const):
    + raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr)
    + raw_js = node.expr.args[0].value
    + print >>self.output, raw_js
    + else:
    + expr = self._callfunc(node.expr, current_klass)
    + print >>self.output, " " + expr + ";"
    +
    + if debugStmt:
    + print >>self.output, "sys.popstack();\n"
    +
    + elif isinstance(node.expr, ast.Const):
    + if node.expr.value is not None: # Empty statements generate ignore None
    + print >>self.output, self._const(node.expr)
    + else:
    + raise TranslationError("unsupported type (in _discard)", node.expr)
    +
    +
    + def _if(self, node, current_klass):
    + for i in range(len(node.tests)):
    + test, consequence = node.tests[i]
    + if i == 0:
    + keyword = "if"
    + else:
    + keyword = "else if"
    +
    + self._if_test(keyword, test, consequence, current_klass)
    +
    + if node.else_:
    + keyword = "else"
    + test = None
    + consequence = node.else_
    +
    + self._if_test(keyword, test, consequence, current_klass)
    +
    +
    + def _if_test(self, keyword, test, consequence, current_klass):
    + if test:
    + expr = self.expr(test, current_klass)
    +
    + print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {"
    + else:
    + print >>self.output, " " + keyword + " {"
    +
    + if isinstance(consequence, ast.Stmt):
    + for child in consequence.nodes:
    + self._stmt(child, current_klass)
    + else:
    + raise TranslationError("unsupported type (in _if_test)", consequence)
    +
    + print >>self.output, " }"
    +
    +
    + def _from(self, node):
    + for name in node.names:
    + # look up "hack" in AppTranslator as to how findFile gets here
    + module_name = node.modname + "." + name[0]
    + try:
    + ff = self.findFile(module_name + ".py")
    + except Exception:
    + ff = None
    + if ff:
    + self.add_imported_module(module_name)
    + else:
    + self.imported_classes[name[0]] = node.modname
    +
    +
    + def _compare(self, node, current_klass):
    + lhs = self.expr(node.expr, current_klass)
    +
    + if len(node.ops) != 1:
    + raise TranslationError("only one ops supported (in _compare)", node)
    +
    + op = node.ops[0][0]
    + rhs_node = node.ops[0][1]
    + rhs = self.expr(rhs_node, current_klass)
    +
    + if op == "==":
    + return "pyjslib.eq(%s, %s)" % (lhs, rhs)
    + if op == "in":
    + return rhs + ".__contains__(" + lhs + ")"
    + elif op == "not in":
    + return "!" + rhs + ".__contains__(" + lhs + ")"
    + elif op == "is":
    + op = "==="
    + elif op == "is not":
    + op = "!=="
    +
    + return "(" + lhs + " " + op + " " + rhs + ")"
    +
    +
    + def _not(self, node, current_klass):
    + expr = self.expr(node.expr, current_klass)
    +
    + return "!(" + expr + ")"
    +
    + def _or(self, node, current_klass):
    + expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')'
    + return expr
    +
    + def _and(self, node, current_klass):
    + expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")"
    + return expr
    +
    + def _for(self, node, current_klass):
    + assign_name = ""
    + assign_tuple = ""
    +
    + # based on Bob Ippolito's Iteration in Javascript code
    + if isinstance(node.assign, ast.AssName):
    + assign_name = node.assign.name
    + self.add_local_arg(assign_name)
    + if node.assign.flags == "OP_ASSIGN":
    + op = "="
    + elif isinstance(node.assign, ast.AssTuple):
    + op = "="
    + i = 0
    + for child in node.assign:
    + child_name = child.name
    + if assign_name == "":
    + assign_name = "temp_" + child_name
    + self.add_local_arg(child_name)
    + assign_tuple += """
    + var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i);
    + """ % locals()
    + i += 1
    + else:
    + raise TranslationError("unsupported type (in _for)", node.assign)
    +
    + if isinstance(node.list, ast.Name):
    + list_expr = self._name(node.list, current_klass)
    + elif isinstance(node.list, ast.Getattr):
    + list_expr = self._getattr(node.list, current_klass)
    + elif isinstance(node.list, ast.CallFunc):
    + list_expr = self._callfunc(node.list, current_klass)
    + else:
    + raise TranslationError("unsupported type (in _for)", node.list)
    +
    + lhs = "var " + assign_name
    + iterator_name = "__" + assign_name
    +
    + print >>self.output, """
    + var %(iterator_name)s = %(list_expr)s.__iter__();
    + try {
    + while (true) {
    + %(lhs)s %(op)s %(iterator_name)s.next();
    + %(assign_tuple)s
    + """ % locals()
    + for node in node.body.nodes:
    + self._stmt(node, current_klass)
    + print >>self.output, """
    + }
    + } catch (e) {
    + if (e.__name__ != pyjslib.StopIteration.__name__) {
    + throw e;
    + }
    + }
    + """ % locals()
    +
    +
    + def _while(self, node, current_klass):
    + test = self.expr(node.test, current_klass)
    + print >>self.output, " while (pyjslib.bool(" + test + ")) {"
    + if isinstance(node.body, ast.Stmt):
    + for child in node.body.nodes:
    + self._stmt(child, current_klass)
    + else:
    + raise TranslationError("unsupported type (in _while)", node.body)
    + print >>self.output, " }"
    +
    +
    + def _const(self, node):
    + if isinstance(node.value, int):
    + return str(node.value)
    + elif isinstance(node.value, float):
    + return str(node.value)
    + elif isinstance(node.value, basestring):
    + v = node.value
    + if isinstance(node.value, unicode):
    + v = v.encode('utf-8')
    + return "String('%s')" % escapejs(v)
    + elif node.value is None:
    + return "null"
    + else:
    + raise TranslationError("unsupported type (in _const)", node)
    +
    + def _unaryadd(self, node, current_klass):
    + return self.expr(node.expr, current_klass)
    +
    + def _unarysub(self, node, current_klass):
    + return "-" + self.expr(node.expr, current_klass)
    +
    + def _add(self, node, current_klass):
    + return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass)
    +
    + def _sub(self, node, current_klass):
    + return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass)
    +
    + def _div(self, node, current_klass):
    + return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass)
    +
    + def _mul(self, node, current_klass):
    + return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass)
    +
    + def _mod(self, node, current_klass):
    + if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType):
    + self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used
    + return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")"
    + return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass)
    +
    + def _invert(self, node, current_klass):
    + return "~" + self.expr(node.expr, current_klass)
    +
    + def _bitand(self, node, current_klass):
    + return " & ".join([self.expr(child, current_klass) for child in node.nodes])
    +
    + def _bitshiftleft(self, node, current_klass):
    + return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass)
    +
    + def _bitshiftright(self, node, current_klass):
    + return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass)
    +
    + def _bitxor(self,node, current_klass):
    + return " ^ ".join([self.expr(child, current_klass) for child in node.nodes])
    +
    + def _bitor(self, node, current_klass):
    + return " | ".join([self.expr(child, current_klass) for child in node.nodes])
    +
    + def _subscript(self, node, current_klass):
    + if node.flags == "OP_APPLY":
    + if len(node.subs) == 1:
    + return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")"
    + else:
    + raise TranslationError("must have one sub (in _subscript)", node)
    + else:
    + raise TranslationError("unsupported flag (in _subscript)", node)
    +
    + def _subscript_stmt(self, node, current_klass):
    + if node.flags == "OP_DELETE":
    + print >>self.output, " " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");"
    + else:
    + raise TranslationError("unsupported flag (in _subscript)", node)
    +
    + def _list(self, node, current_klass):
    + return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
    +
    + def _dict(self, node, current_klass):
    + items = []
    + for x in node.items:
    + key = self.expr(x[0], current_klass)
    + value = self.expr(x[1], current_klass)
    + items.append("[" + key + ", " + value + "]")
    + return "new pyjslib.Dict([" + ", ".join(items) + "])"
    +
    + def _tuple(self, node, current_klass):
    + return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
    +
    + def _lambda(self, node, current_klass):
    + if node.varargs:
    + raise TranslationError("varargs are not supported in Lambdas", node)
    + if node.kwargs:
    + raise TranslationError("kwargs are not supported in Lambdas", node)
    + res = cStringIO.StringIO()
    + arg_names = list(node.argnames)
    + function_args = ", ".join(arg_names)
    + for child in node.getChildNodes():
    + expr = self.expr(child, None)
    + print >> res, "function (%s){" % function_args
    + self._default_args_handler(node, arg_names, None,
    + output=res)
    + print >> res, 'return %s;}' % expr
    + return res.getvalue()
    +
    + def _slice(self, node, current_klass):
    + if node.flags == "OP_APPLY":
    + lower = "null"
    + upper = "null"
    + if node.lower != None:
    + lower = self.expr(node.lower, current_klass)
    + if node.upper != None:
    + upper = self.expr(node.upper, current_klass)
    + return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")"
    + else:
    + raise TranslationError("unsupported flag (in _slice)", node)
    +
    + def _global(self, node, current_klass):
    + for name in node.names:
    + self.method_imported_globals.add(name)
    +
    + def expr(self, node, current_klass):
    + if isinstance(node, ast.Const):
    + return self._const(node)
    + # @@@ not sure if the parentheses should be here or in individual operator functions - JKT
    + elif isinstance(node, ast.Mul):
    + return " ( " + self._mul(node, current_klass) + " ) "
    + elif isinstance(node, ast.Add):
    + return " ( " + self._add(node, current_klass) + " ) "
    + elif isinstance(node, ast.Sub):
    + return " ( " + self._sub(node, current_klass) + " ) "
    + elif isinstance(node, ast.Div):
    + return " ( " + self._div(node, current_klass) + " ) "
    + elif isinstance(node, ast.Mod):
    + return self._mod(node, current_klass)
    + elif isinstance(node, ast.UnaryAdd):
    + return self._unaryadd(node, current_klass)
    + elif isinstance(node, ast.UnarySub):
    + return self._unarysub(node, current_klass)
    + elif isinstance(node, ast.Not):
    + return self._not(node, current_klass)
    + elif isinstance(node, ast.Or):
    + return self._or(node, current_klass)
    + elif isinstance(node, ast.And):
    + return self._and(node, current_klass)
    + elif isinstance(node, ast.Invert):
    + return self._invert(node, current_klass)
    + elif isinstance(node, ast.Bitand):
    + return "("+self._bitand(node, current_klass)+")"
    + elif isinstance(node,ast.LeftShift):
    + return self._bitshiftleft(node, current_klass)
    + elif isinstance(node, ast.RightShift):
    + return self._bitshiftright(node, current_klass)
    + elif isinstance(node, ast.Bitxor):
    + return "("+self._bitxor(node, current_klass)+")"
    + elif isinstance(node, ast.Bitor):
    + return "("+self._bitor(node, current_klass)+")"
    + elif isinstance(node, ast.Compare):
    + return self._compare(node, current_klass)
    + elif isinstance(node, ast.CallFunc):
    + return self._callfunc(node, current_klass)
    + elif isinstance(node, ast.Name):
    + return self._name(node, current_klass)
    + elif isinstance(node, ast.Subscript):
    + return self._subscript(node, current_klass)
    + elif isinstance(node, ast.Getattr):
    + return self._getattr(node, current_klass)
    + elif isinstance(node, ast.List):
    + return self._list(node, current_klass)
    + elif isinstance(node, ast.Dict):
    + return self._dict(node, current_klass)
    + elif isinstance(node, ast.Tuple):
    + return self._tuple(node, current_klass)
    + elif isinstance(node, ast.Slice):
    + return self._slice(node, current_klass)
    + elif isinstance(node, ast.Lambda):
    + return self._lambda(node, current_klass)
    + else:
    + raise TranslationError("unsupported type (in expr)", node)
    +
    +
    +
    +import cStringIO
    +
    +def translate(file_name, module_name, debug=False):
    + f = file(file_name, "r")
    + src = f.read()
    + f.close()
    + output = cStringIO.StringIO()
    + mod = compiler.parseFile(file_name)
    + t = Translator(module_name, module_name, module_name, src, debug, mod, output)
    + return output.getvalue()
    +
    +
    +class PlatformParser:
    + def __init__(self, platform_dir = "", verbose=True):
    + self.platform_dir = platform_dir
    + self.parse_cache = {}
    + self.platform = ""
    + self.verbose = verbose
    +
    + def setPlatform(self, platform):
    + self.platform = platform
    +
    + def parseModule(self, module_name, file_name):
    +
    + importing = False
    + if not self.parse_cache.has_key(file_name):
    + importing = True
    + mod = compiler.parseFile(file_name)
    + self.parse_cache[file_name] = mod
    + else:
    + mod = self.parse_cache[file_name]
    +
    + override = False
    + platform_file_name = self.generatePlatformFilename(file_name)
    + if self.platform and os.path.isfile(platform_file_name):
    + mod = copy.deepcopy(mod)
    + mod_override = compiler.parseFile(platform_file_name)
    + self.merge(mod, mod_override)
    + override = True
    +
    + if self.verbose:
    + if override:
    + print "Importing %s (Platform %s)" % (module_name, self.platform)
    + elif importing:
    + print "Importing %s" % (module_name)
    +
    + return mod, override
    +
    + def generatePlatformFilename(self, file_name):
    + (module_name, extension) = os.path.splitext(os.path.basename(file_name))
    + platform_file_name = module_name + self.platform + extension
    +
    + return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name)
    +
    + def merge(self, tree1, tree2):
    + for child in tree2.node:
    + if isinstance(child, ast.Function):
    + self.replaceFunction(tree1, child.name, child)
    + elif isinstance(child, ast.Class):
    + self.replaceClassMethods(tree1, child.name, child)
    +
    + return tree1
    +
    + def replaceFunction(self, tree, function_name, function_node):
    + # find function to replace
    + for child in tree.node:
    + if isinstance(child, ast.Function) and child.name == function_name:
    + self.copyFunction(child, function_node)
    + return
    + raise TranslationError("function not found: " + function_name, function_node)
    +
    + def replaceClassMethods(self, tree, class_name, class_node):
    + # find class to replace
    + old_class_node = None
    + for child in tree.node:
    + if isinstance(child, ast.Class) and child.name == class_name:
    + old_class_node = child
    + break
    +
    + if not old_class_node:
    + raise TranslationError("class not found: " + class_name, class_node)
    +
    + # replace methods
    + for function_node in class_node.code:
    + if isinstance(function_node, ast.Function):
    + found = False
    + for child in old_class_node.code:
    + if isinstance(child, ast.Function) and child.name == function_node.name:
    + found = True
    + self.copyFunction(child, function_node)
    + break
    +
    + if not found:
    + raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node)
    +
    + def copyFunction(self, target, source):
    + target.code = source.code
    + target.argnames = source.argnames
    + target.defaults = source.defaults
    + target.doc = source.doc # @@@ not sure we need to do this any more
    +
    +def dotreplace(fname):
    + path, ext = os.path.splitext(fname)
    + return path.replace(".", "/") + ext
    +
    +class AppTranslator:
    +
    + def __init__(self, library_dirs=[], parser=None, dynamic=False,
    + optimize=False, verbose=True):
    + self.extension = ".py"
    + self.optimize = optimize
    + self.library_modules = []
    + self.overrides = {}
    + self.library_dirs = path + library_dirs
    + self.dynamic = dynamic
    + self.verbose = verbose
    +
    + if not parser:
    + self.parser = PlatformParser()
    + else:
    + self.parser = parser
    +
    + self.parser.dynamic = dynamic
    +
    + def findFile(self, file_name):
    + if os.path.isfile(file_name):
    + return file_name
    +
    + for library_dir in self.library_dirs:
    + file_name = dotreplace(file_name)
    + full_file_name = os.path.join(
    + os.path.abspath(os.path.dirname(__file__)), library_dir, file_name)
    + if os.path.isfile(full_file_name):
    + return full_file_name
    +
    + fnameinit, ext = os.path.splitext(file_name)
    + fnameinit = fnameinit + "/__init__.py"
    +
    + full_file_name = os.path.join(
    + os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit)
    + if os.path.isfile(full_file_name):
    + return full_file_name
    +
    + raise Exception("file not found: " + file_name)
    +
    + def _translate(self, module_name, is_app=True, debug=False,
    + imported_js=set()):
    + if module_name not in self.library_modules:
    + self.library_modules.append(module_name)
    +
    + file_name = self.findFile(module_name + self.extension)
    +
    + output = cStringIO.StringIO()
    +
    + f = file(file_name, "r")
    + src = f.read()
    + f.close()
    +
    + mod, override = self.parser.parseModule(module_name, file_name)
    + if override:
    + override_name = "%s.%s" % (self.parser.platform.lower(),
    + module_name)
    + self.overrides[override_name] = override_name
    + if is_app:
    + mn = '__main__'
    + else:
    + mn = module_name
    + t = Translator(mn, module_name, module_name,
    + src, debug, mod, output, self.dynamic, self.optimize,
    + self.findFile)
    +
    + module_str = output.getvalue()
    + imported_js.update(set(t.imported_js))
    + imported_modules_str = ""
    + for module in t.imported_modules:
    + if module not in self.library_modules:
    + self.library_modules.append(module)
    + #imported_js.update(set(t.imported_js))
    + #imported_modules_str += self._translate(
    + # module, False, debug=debug, imported_js=imported_js)
    +
    + return imported_modules_str + module_str
    +
    +
    + def translate(self, module_name, is_app=True, debug=False,
    + library_modules=[]):
    + app_code = cStringIO.StringIO()
    + lib_code = cStringIO.StringIO()
    + imported_js = set()
    + self.library_modules = []
    + self.overrides = {}
    + for library in library_modules:
    + if library.endswith(".js"):
    + imported_js.add(library)
    + continue
    + self.library_modules.append(library)
    + if self.verbose:
    + print 'Including LIB', library
    + print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n'
    + print >> lib_code, self._translate(
    + library, False, debug=debug, imported_js=imported_js)
    +
    + print >> lib_code, "/* initialize static library */"
    + print >> lib_code, "%s%s();\n" % (UU, library)
    +
    + print >> lib_code, '\n//\n// END LIB '+library+'\n//\n'
    + if module_name:
    + print >> app_code, self._translate(
    + module_name, is_app, debug=debug, imported_js=imported_js)
    + for js in imported_js:
    + path = self.findFile(js)
    + if os.path.isfile(path):
    + if self.verbose:
    + print 'Including JS', js
    + print >> lib_code, '\n//\n// BEGIN JS '+js+'\n//\n'
    + print >> lib_code, file(path).read()
    + print >> lib_code, '\n//\n// END JS '+js+'\n//\n'
    + else:
    + print >>sys.stderr, 'Warning: Unable to find imported javascript:', js
    + return lib_code.getvalue(), app_code.getvalue()
    +
    +usage = """
    + usage: %s file_name [module_name]
    +"""
    +
    +def main():
    + import sys
    + if len(sys.argv)<2:
    + print >> sys.stderr, usage % sys.argv[0]
    + sys.exit(1)
    + file_name = os.path.abspath(sys.argv[1])
    + if not os.path.isfile(file_name):
    + print >> sys.stderr, "File not found %s" % file_name
    + sys.exit(1)
    + if len(sys.argv) > 2:
    + module_name = sys.argv[2]
    + else:
    + module_name = None
    + print translate(file_name, module_name),
    +
    +if __name__ == "__main__":
    + main()
    +
    --- /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 @@
    +import wx
    +import os, sys, shutil
    +
    +from ConfigTree import opjimg
    +from py_ext import PythonCodeTemplate
    +
    +from pyjs import translate
    +
    +from docutils import *
    +
    +class RootClass:
    +
    + ConfNodeMethods = [
    + {"bitmap" : os.path.join("images","ImportSVG"),
    + "name" : _("Import SVG"),
    + "tooltip" : _("Import SVG"),
    + "method" : "_ImportSVG"},
    + {"bitmap" : os.path.join("images","ImportSVG"),
    + "name" : _("Inkscape"),
    + "tooltip" : _("Create HMI"),
    + "method" : "_StartInkscape"},
    + ]
    +
    + def ConfNodePath(self):
    + return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType)
    +
    + def _getSVGpath(self):
    + # define name for IEC raw code file
    + return os.path.join(self.CTNPath(), "gui.svg")
    +
    + def _getSVGUIserverpath(self):
    + return os.path.join(os.path.dirname(__file__), "svgui_server.py")
    +
    + def CTNGenerate_C(self, buildpath, locations):
    + """
    + Return C code generated by iec2c compiler
    + when _generate_softPLC have been called
    + @param locations: ignored
    + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    + """
    +
    + current_location = self.GetCurrentLocation()
    + # define a unique name for the generated C file
    + location_str = "_".join(map(lambda x:str(x), current_location))
    +
    + res = ([], "", False)
    +
    + svgfile=self._getSVGpath()
    + if os.path.exists(svgfile):
    + res += (("gui.svg", file(svgfile,"rb")),)
    +
    + svguiserverfile = open(self._getSVGUIserverpath(), 'r')
    + svguiservercode = svguiserverfile.read()
    + svguiserverfile.close()
    +
    + svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js")
    + svguilibfile = open(svguilibpath, 'w')
    + svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys"))
    + svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read())
    + svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib"))
    + svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib"))
    + svguilibfile.write("pyjslib();\nsvguilib();\n")
    + svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read())
    + svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read())
    + svguilibfile.close()
    + jsmodules = {"LiveSVGPage": "svguilib.js"}
    + res += (("svguilib.js", file(svguilibpath,"rb")),)
    +
    + runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
    + runtimefile = open(runtimefile_path, 'w')
    + runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"})
    + runtimefile.write("""
    +def _runtime_%(location)s_begin():
    + website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
    +
    +def _runtime_%(location)s_cleanup():
    + website.UnLoadHMI()
    +
    +""" % {"location": location_str,
    + "svgui_class": "SVGUI_HMI",
    + "jsmodules" : str(jsmodules),
    + })
    + runtimefile.close()
    +
    + res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),)
    +
    + return res
    +
    + def _ImportSVG(self):
    + dialog = wx.FileDialog(self.GetCTRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "", _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN)
    + if dialog.ShowModal() == wx.ID_OK:
    + svgpath = dialog.GetPath()
    + if os.path.isfile(svgpath):
    + shutil.copy(svgpath, self._getSVGpath())
    + else:
    + self.GetCTRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath)
    + dialog.Destroy()
    +
    + def _StartInkscape(self):
    + svgfile = self._getSVGpath()
    + open_inkscape = True
    + if not self.GetCTRoot().CheckProjectPathPerm():
    + dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
    + _("You don't have write permissions.\nOpen Inkscape anyway ?"),
    + _("Open Inkscape"),
    + wx.YES_NO|wx.ICON_QUESTION)
    + open_inkscape = dialog.ShowModal() == wx.ID_YES
    + dialog.Destroy()
    + if open_inkscape:
    + if not os.path.isfile(svgfile):
    + svgfile = None
    + open_svg(svgfile)
    --- /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 @@
    +#!/usr/bin/python
    +# -*- coding: utf-8 -*-
    +
    +import os
    +
    +from nevow import rend, appserver, inevow, tags, loaders, athena
    +import simplejson as json
    +
    +svgfile = '%(svgfile)s'
    +
    +svguiWidgets = {}
    +
    +currentId = 0
    +def getNewId():
    + global currentId
    + currentId += 1
    + return currentId
    +
    +class SvguiWidget:
    +
    + def __init__(self, classname, id, **kwargs):
    + self.classname = classname
    + self.id = id
    + self.attrs = kwargs.copy()
    + self.inputs = {}
    + self.outputs = {}
    + self.inhibit = False
    + self.changed = False
    +
    + def setinput(self, attrname, value):
    + self.inputs[attrname] = value
    +
    + def getinput(self, attrname, default=None):
    + if not self.inputs.has_key(attrname):
    + self.inputs[attrname] = default
    + return self.inputs[attrname]
    +
    + def setoutput(self, attrname, value):
    + if self.outputs.get(attrname) != value:
    + self.outputs[attrname] = value
    + self.changed = True
    + self.RefreshInterface()
    +
    + def updateoutputs(self, **kwargs):
    + for attrname, value in kwargs.iteritems():
    + if self.outputs.get(attrname) != value:
    + self.outputs[attrname] = value
    + self.changed = True
    + self.RefreshInterface()
    +
    + def RefreshInterface(self):
    + interface = website.getHMI()
    + if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit:
    + self.changed = False
    + d = interface.sendData(self)
    + if d is not None:
    + self.inhibit = True
    + d.addCallback(self.InterfaceRefreshed)
    +
    + def InterfaceRefreshed(self, result):
    + self.inhibit = False
    + if self.changed:
    + self.RefreshInterface()
    +
    +def get_object_init_state(obj):
    + # Convert objects to a dictionary of their representation
    + attrs = obj.attrs.copy()
    + attrs.update(obj.inputs)
    + d = { '__class__': obj.classname,
    + 'id': obj.id,
    + 'kwargs': json.dumps(attrs),
    + }
    + return d
    +
    +def get_object_current_state(obj):
    + # Convert objects to a dictionary of their representation
    + d = { '__class__': obj.classname,
    + 'id': obj.id,
    + 'kwargs': json.dumps(obj.outputs),
    + }
    + return d
    +
    +class SVGUI_HMI(website.PLCHMI):
    + jsClass = u"LiveSVGPage.LiveSVGWidget"
    +
    + docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[
    + tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))),
    + ])
    +
    + def HMIinitialisation(self):
    + gadgets = []
    + for gadget in svguiWidgets.values():
    + gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
    + d = self.callRemote('init', gadgets)
    + d.addCallback(self.HMIinitialised)
    +
    + def sendData(self,data):
    + if self.initialised:
    + return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
    + return None
    +
    + def setattr(self, id, attrname, value):
    + svguiWidgets[id].setinput(attrname, value)
    +
    +def createSVGUIControl(*args, **kwargs):
    + id = getNewId()
    + gad = SvguiWidget(args[0], id, **kwargs)
    + svguiWidgets[id] = gad
    + gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
    + interface = website.getHMI()
    + if isinstance(interface, SVGUI_HMI) and interface.initialised:
    + interface.callRemote('init', gadget)
    + return id
    +
    +def setAttr(id, attrname, value):
    + gad = svguiWidgets.get(id, None)
    + if gad is not None:
    + gad.setoutput(attrname, value)
    +
    +def updateAttr(id, **kwargs):
    + gad = svguiWidgets.get(id, None)
    + if gad is not None:
    + gad.updateoutput(**kwargs)
    +
    +def getAttr(id, attrname, default=None):
    + gad = svguiWidgets.get(id, None)
    + if gad is not None:
    + return gad.getinput(attrname, default)
    + return default
    +
    --- /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 @@
    +
    +class button:
    +
    + def __init__(self, parent, id, args):
    + self.parent = parent
    + self.id = id
    + self.back_elt = getSVGElementById(args.back_id)
    + self.sele_elt = getSVGElementById(args.sele_id)
    + self.toggle = args.toggle
    + self.active = args.active
    + if args.state != undefined:
    + self.state = args.state
    + else:
    + self.state = False
    + self.dragging = False
    + if self.toggle:
    + self.up = not self.state
    + else:
    + self.up = True
    +
    + # Add event on each element of the button
    + if self.active:
    + self.back_elt.addEventListener("mouseup", self, False)
    + self.back_elt.addEventListener("mousedown", self, False)
    + self.back_elt.addEventListener("mouseover", self, False)
    + self.back_elt.addEventListener("mouseout", self, False)
    +
    + self.sele_elt.addEventListener("mouseup", self, False)
    + self.sele_elt.addEventListener("mousedown", self, False)
    + self.sele_elt.addEventListener("mouseover", self, False)
    + self.sele_elt.addEventListener("mouseout", self, False)
    +
    + blockSVGElementDrag(self.back_elt)
    + blockSVGElementDrag(self.sele_elt)
    +
    + self.updateElements()
    +
    + # method to display the current state of interface
    + def updateElements(self):
    + if self.up:
    + self.sele_elt.setAttribute("display", "none")
    + self.back_elt.removeAttribute("display")
    + else:
    + self.sele_elt.removeAttribute("display")
    + self.back_elt.setAttribute("display", "none")
    +
    + def updateValues(self, values):
    + if values.state != self.state:
    + self.state = values.state
    + self.up = not self.state
    + updateAttr(self.id, 'state', self.state)
    + self.updateElements()
    +
    + def handleEvent(self, evt):
    + # Quand le bouton de la souris est presse
    + if evt.type == "mousedown":
    + evt.stopPropagation()
    + setCurrentObject(self)
    +
    + self.dragging = True
    +
    + if self.toggle:
    + self.up = self.state
    + else:
    + self.up = False
    + self.state = True
    + updateAttr(self.id, 'state', self.state)
    + self.updateElements()
    +
    + if isCurrentObject(self) and self.dragging:
    + # Quand le bouton est survole
    + if evt.type == "mouseover" and self.toggle:
    + self.up = self.state
    + self.updateElements()
    +
    + # Quand le curseur quitte la zone du bouton
    + elif evt.type == "mouseout" and self.toggle:
    + self.up = not self.state
    + self.updateElements()
    +
    + # Quand le bouton de la souris est relache
    + elif evt.type == "mouseup":
    + evt.stopPropagation()
    + if self.toggle and self.up == self.state:
    + self.state = not self.state
    + updateAttr(self.id, 'state', self.state)
    + elif not self.toggle:
    + self.up = True
    + self.state = False
    + updateAttr(self.id, 'state', self.state)
    + self.updateElements()
    + self.dragging = False
    +
    +class textControl:
    +
    + def __init__(self, parent, id, args):
    + self.parent = parent
    + self.id = id
    + self.back_elt = getSVGElementById(args.back_id)
    + if args.text != undefined:
    + self.text = args.text
    + else:
    + self.text = ""
    + self.updateElements()
    +
    + def updateValues(self, values):
    + if values.text != self.value:
    + self.text = values.text
    + updateAttr(self.id, 'text', self.text)
    + self.updateElements()
    +
    + def updateElements(self):
    + self.back_elt.firstChild.firstChild.textContent = self.text
    +
    + def handleEvent(self, evt):
    + pass
    +
    \ No newline at end of file
    --- /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 @@
    +WxGlade HMI
    \ 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 @@
    +import wx
    +import os, sys
    +from xml.dom import minidom
    +
    +from ConfigTree import opjimg
    +from py_ext import PythonCodeTemplate
    +
    +class RootClass(PythonCodeTemplate):
    +
    + ConfNodeMethods = [
    + {"bitmap" : opjimg("editWXGLADE"),
    + "name" : _("WXGLADE GUI"),
    + "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
    + "method" : "_editWXGLADE"},
    + ]
    +
    + def _getWXGLADEpath(self):
    + # define name for IEC raw code file
    + return os.path.join(self.CTNPath(), "hmi.wxg")
    +
    + def launch_wxglade(self, options, wait=False):
    + from wxglade import __file__ as fileName
    + path = os.path.dirname(fileName)
    + glade = os.path.join(path, 'wxglade.py')
    + if wx.Platform == '__WXMSW__':
    + glade = "\"%s\""%glade
    + mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait]
    + os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options)
    +
    +
    + def CTNGenerate_C(self, buildpath, locations):
    + """
    + Return C code generated by iec2c compiler
    + when _generate_softPLC have been called
    + @param locations: ignored
    + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    + """
    +
    + current_location = self.GetCurrentLocation()
    + # define a unique name for the generated C file
    + location_str = "_".join(map(lambda x:str(x), current_location))
    +
    + runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
    + runtimefile = open(runtimefile_path, 'w')
    +
    + hmi_frames = {}
    +
    + wxgfile_path=self._getWXGLADEpath()
    + if os.path.exists(wxgfile_path):
    + wxgfile = open(wxgfile_path, 'r')
    + wxgtree = minidom.parse(wxgfile)
    + wxgfile.close()
    +
    + for node in wxgtree.childNodes[1].childNodes:
    + if node.nodeType == wxgtree.ELEMENT_NODE:
    + hmi_frames[node._attrs["name"].value] = node._attrs["class"].value
    +
    + hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py")
    + if wx.Platform == '__WXMSW__':
    + wxgfile_path = "\"%s\""%wxgfile_path
    + wxghmipyfile_path = "\"%s\""%hmipyfile_path
    + else:
    + wxghmipyfile_path = hmipyfile_path
    + self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True)
    +
    + hmipyfile = open(hmipyfile_path, 'r')
    + runtimefile.write(hmipyfile.read())
    + hmipyfile.close()
    +
    + runtimefile.write(self.GetPythonCode())
    + runtimefile.write("""
    +%(declare)s
    +
    +def _runtime_%(location)s_begin():
    + global %(global)s
    +
    + def OnCloseFrame(evt):
    + wx.MessageBox(_("Please stop PLC to close"))
    +
    + %(init)s
    +
    +def _runtime_%(location)s_cleanup():
    + global %(global)s
    +
    + %(cleanup)s
    +
    +""" % {"location": location_str,
    + "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())),
    + "global": ",".join(hmi_frames.keys()),
    + "init": "\n".join(map(lambda x: """
    + %(name)s = %(class)s(None)
    + %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
    + %(name)s.Show()
    +""" % {"name": x[0], "class": x[1]},
    + hmi_frames.items())),
    + "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))})
    + runtimefile.close()
    +
    + return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
    +
    + def _editWXGLADE(self):
    + wxg_filename = self._getWXGLADEpath()
    + open_wxglade = True
    + if not self.GetCTRoot().CheckProjectPathPerm():
    + dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
    + _("You don't have write permissions.\nOpen wxGlade anyway ?"),
    + _("Open wxGlade"),
    + wx.YES_NO|wx.ICON_QUESTION)
    + open_wxglade = dialog.ShowModal() == wx.ID_YES
    + dialog.Destroy()
    + if open_wxglade:
    + if not os.path.exists(wxg_filename):
    + hmi_name = self.BaseParams.getName()
    + open(wxg_filename,"w").write("""<?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>
    + <title>frame_1</title>
    + </object>
    + </application>
    + """ % {"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
    + * flags.
    + *
    + * */
    +
    +#include "iec_types_all.h"
    +#include "POUS.h"
    +#include <string.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*/
    +static int PythonState;
    +#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);
    +void LockPython(void);
    +
    +int __init_%(location)s()
    +{
    + int i;
    + /* 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++)
    + EvalFBs[i] = NULL;
    + return 0;
    +}
    +
    +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_PLC :
    + 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();
    + }
    + UnLockPython();
    + }
    +}
    +/**
    + * 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){
    + /* mark as trigged */
    + __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);
    + /* Mark as free */
    + __SET_VAR(data__->, STATE, PYTHON_FB_FREE);
    + /* mark as not trigged */
    + if(!poll)
    + __SET_VAR(data__->, TRIGGED, 0);
    + /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
    + }else if(poll){
    + /* 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 */
    + if(!poll){
    + /* when not polling, a new answer imply reseting ack*/
    + __SET_VAR(data__->, ACK, 0);
    + }else{
    + /* when in polling, acting reset trigger */
    + __SET_VAR(data__->, TRIGGED, 0);
    + }
    + /* Mark FB busy */
    + __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);*/
    + /* Get a new line */
    + Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
    + }
    + }
    +}
    +
    +char* PythonIterator(char* result)
    +{
    + char* next_command;
    + PYTHON_EVAL* data__;
    + //printf("PythonIterator result %%s\n", result);
    + /*emergency exit*/
    + if(PythonState & PYTHON_FINISHED) return NULL;
    + /* take python mutex to prevent changing PLC data while PLC running */
    + LockPython();
    + /* Get current FB */
    + 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 */
    + if(result){
    + /* Get results len */
    + __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));
    + }else{
    + __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);
    + /* Get a new line */
    + 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)
    + {
    + UnLockPython();
    + /* wait next FB to eval */
    + //printf("PythonIterator wait\n");
    + if(WaitPythonCommands()) return NULL;
    + /*emergency exit*/
    + if(PythonState & PYTHON_FINISHED) return NULL;
    + LockPython();
    + }
    + /* 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 */
    + UnLockPython();
    + /* return the next command to eval */
    + return next_command;
    +}
    +
    --- /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"
    + productName="Beremiz"
    + productVersion="0.0"
    + creationDateTime="2008-12-14T16:53:26"/>
    + <contentHeader name="Beremiz non-standard POUs library"
    + modificationDateTime="2008-12-23T22:35:46">
    + <coordinateInfo>
    + <fbd>
    + <scaling x="0" y="0"/>
    + </fbd>
    + <ld>
    + <scaling x="0" y="0"/>
    + </ld>
    + <sfc>
    + <scaling x="0" y="0"/>
    + </sfc>
    + </coordinateInfo>
    + </contentHeader>
    + <types>
    + <dataTypes/>
    + <pous>
    + <pou name="python_eval" pouType="functionBlock">
    + <interface>
    + <inputVars>
    + <variable name="TRIG">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="CODE">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </inputVars>
    + <outputVars>
    + <variable name="ACK">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="RESULT">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </outputVars>
    + <localVars>
    + <variable name="STATE">
    + <type>
    + <DWORD/>
    + </type>
    + </variable>
    + <variable name="BUFFER">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="PREBUFFER">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="TRIGM1">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="TRIGGED">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <ST>
    +<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(0, data__);}]]>
    + </ST>
    + </body>
    + </pou>
    + <pou name="python_poll" pouType="functionBlock">
    + <interface>
    + <inputVars>
    + <variable name="TRIG">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="CODE">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </inputVars>
    + <outputVars>
    + <variable name="ACK">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="RESULT">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </outputVars>
    + <localVars>
    + <variable name="STATE">
    + <type>
    + <DWORD/>
    + </type>
    + </variable>
    + <variable name="BUFFER">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="PREBUFFER">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + <variable name="TRIGM1">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="TRIGGED">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <ST>
    +<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(1,(PYTHON_EVAL*)(void*)data__);}]]>
    + </ST>
    + </body>
    + </pou>
    + <pou name="python_gear" pouType="functionBlock">
    + <interface>
    + <inputVars>
    + <variable name="N">
    + <type>
    + <USINT/>
    + </type>
    + </variable>
    + <variable name="TRIG">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="CODE">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </inputVars>
    + <outputVars>
    + <variable name="ACK">
    + <type>
    + <BOOL/>
    + </type>
    + </variable>
    + <variable name="RESULT">
    + <type>
    + <string/>
    + </type>
    + </variable>
    + </outputVars>
    + <localVars>
    + <variable name="py_eval">
    + <type>
    + <derived name="python_eval"/>
    + </type>
    + </variable>
    + <variable name="COUNTER">
    + <type>
    + <USINT/>
    + </type>
    + </variable>
    + </localVars>
    + </interface>
    + <body>
    + <FBD>
    + <block localId="1" width="125" height="110" typeName="python_eval" instanceName="py_eval">
    + <position x="525" y="580"/>
    + <inputVariables>
    + <variable formalParameter="TRIG">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="CODE">
    + <connectionPointIn>
    + <relPosition x="0" y="85"/>
    + <connection refLocalId="4">
    + <position x="525" y="665"/>
    + <position x="370" y="665"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="ACK">
    + <connectionPointOut>
    + <relPosition x="125" y="40"/>
    + </connectionPointOut>
    + </variable>
    + <variable formalParameter="RESULT">
    + <connectionPointOut>
    + <relPosition x="125" y="85"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="2" height="35" width="25">
    + <position x="435" y="270"/>
    + <connectionPointOut>
    + <relPosition x="25" y="15"/>
    + </connectionPointOut>
    + <expression>N</expression>
    + </inVariable>
    + <inVariable localId="3" height="35" width="55">
    + <position x="275" y="585"/>
    + <connectionPointOut>
    + <relPosition x="55" y="15"/>
    + </connectionPointOut>
    + <expression>TRIG</expression>
    + </inVariable>
    + <inVariable localId="4" height="35" width="55">
    + <position x="315" y="650"/>
    + <connectionPointOut>
    + <relPosition x="55" y="15"/>
    + </connectionPointOut>
    + <expression>CODE</expression>
    + </inVariable>
    + <outVariable localId="5" height="35" width="45">
    + <position x="740" y="605"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="1" formalParameter="ACK">
    + <position x="740" y="620"/>
    + <position x="650" y="620"/>
    + </connection>
    + </connectionPointIn>
    + <expression>ACK</expression>
    + </outVariable>
    + <outVariable localId="6" height="35" width="75">
    + <position x="740" y="650"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="1" formalParameter="RESULT">
    + <position x="740" y="665"/>
    + <position x="650" y="665"/>
    + </connection>
    + </connectionPointIn>
    + <expression>RESULT</expression>
    + </outVariable>
    + <block localId="7" width="80" height="65" typeName="AND">
    + <position x="385" y="545"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="55"/>
    + <connection refLocalId="3">
    + <position x="385" y="600"/>
    + <position x="330" y="600"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="80" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="9" height="35" width="85">
    + <position x="240" y="330"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>COUNTER</expression>
    + </inVariable>
    + <block localId="10" width="80" height="65" typeName="ADD">
    + <position x="380" y="330"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <relPosition x="0" y="55"/>
    + <connection refLocalId="11">
    + <position x="380" y="385"/>
    + <position x="325" y="385"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="80" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="11" height="35" width="85">
    + <position x="240" y="370"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>USINT#1</expression>
    + </inVariable>
    + <block localId="13" width="80" height="65" typeName="EQ">
    + <position x="535" y="255"/>
    + <inputVariables>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="30"/>
    + <connection refLocalId="2">
    + <position x="535" y="285"/>
    + <position x="460" y="285"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN2">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="80" y="30"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <block localId="15" width="80" height="135" typeName="SEL">
    + <position x="785" y="245"/>
    + <inputVariables>
    + <variable formalParameter="G">
    + <connectionPointIn>
    + <relPosition x="0" y="40"/>
    + <connection refLocalId="13" formalParameter="OUT">
    + <position x="785" y="285"/>
    + <position x="615" y="285"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN0">
    + <connectionPointIn>
    + <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"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + <variable formalParameter="IN1">
    + <connectionPointIn>
    + <relPosition x="0" y="115"/>
    + <connection refLocalId="16">
    + <position x="785" y="360"/>
    + <position x="760" y="360"/>
    + </connection>
    + </connectionPointIn>
    + </variable>
    + </inputVariables>
    + <inOutVariables/>
    + <outputVariables>
    + <variable formalParameter="OUT">
    + <connectionPointOut>
    + <relPosition x="80" y="40"/>
    + </connectionPointOut>
    + </variable>
    + </outputVariables>
    + </block>
    + <inVariable localId="16" height="35" width="85">
    + <position x="675" y="345"/>
    + <connectionPointOut>
    + <relPosition x="85" y="15"/>
    + </connectionPointOut>
    + <expression>USINT#0</expression>
    + </inVariable>
    + <outVariable localId="17" height="35" width="85">
    + <position x="905" y="270"/>
    + <connectionPointIn>
    + <relPosition x="0" y="15"/>
    + <connection refLocalId="15" formalParameter="OUT">
    + <position x="905" y="285"/>
    + <position x="865" y="285"/>
    + </connection>
    + </connectionPointIn>
    + <expression>COUNTER</expression>
    + </outVariable>
    + </FBD>
    + </body>
    + </pou>
    + </pous>
    + </types>
    + <instances>
    + <configurations/>
    + </instances>
    +</project>
    --- /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 @@
    +import wx
    +import os
    +import modules
    +from ConfigTree import ConfigTreeNode, opjimg
    +from PLCControler import UndoBuffer
    +from PythonEditor import PythonEditor
    +
    +from xml.dom import minidom
    +from xmlclass import *
    +import cPickle
    +
    +PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd"))
    +
    +class PythonCodeTemplate:
    +
    + EditorType = PythonEditor
    +
    + def __init__(self):
    +
    + self.ConfNodeMethods.insert(0,
    + {"bitmap" : opjimg("editPYTHONcode"),
    + "name" : _("Edit Python File"),
    + "tooltip" : _("Edit Python File"),
    + "method" : "_OpenView"},
    + )
    +
    + filepath = self.PythonFileName()
    +
    + self.PythonCode = PythonClasses["Python"]()
    + if os.path.isfile(filepath):
    + xmlfile = open(filepath, 'r')
    + tree = minidom.parse(xmlfile)
    + xmlfile.close()
    +
    + for child in tree.childNodes:
    + if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
    + self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
    + self.CreatePythonBuffer(True)
    + else:
    + self.CreatePythonBuffer(False)
    + self.OnCTNSave()
    +
    + def ConfNodePath(self):
    + return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType)
    +
    + def PythonFileName(self):
    + return os.path.join(self.CTNPath(), "py_ext.xml")
    +
    + def GetFilename(self):
    + if self.PythonBuffer.IsCurrentSaved():
    + return "py_ext"
    + else:
    + return "~py_ext~"
    +
    + def SetPythonCode(self, text):
    + self.PythonCode.settext(text)
    +
    + def GetPythonCode(self):
    + return self.PythonCode.gettext()
    +
    + def CTNTestModified(self):
    + return self.ChangesToSave or not self.PythonIsSaved()
    +
    + def OnCTNSave(self):
    + filepath = self.PythonFileName()
    +
    + text = "<?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"))
    + xmlfile.close()
    +
    + self.MarkPythonAsSaved()
    + return True
    +
    +#-------------------------------------------------------------------------------
    +# Current Buffering Management Functions
    +#-------------------------------------------------------------------------------
    +
    + """
    + Return a copy of the project
    + """
    + def Copy(self, model):
    + return cPickle.loads(cPickle.dumps(model))
    +
    + def CreatePythonBuffer(self, saved):
    + self.Buffering = False
    + self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
    +
    + def BufferPython(self):
    + self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
    +
    + def StartBuffering(self):
    + self.Buffering = True
    +
    + def EndBuffering(self):
    + if self.Buffering:
    + self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
    + self.Buffering = False
    +
    + def MarkPythonAsSaved(self):
    + self.EndBuffering()
    + self.PythonBuffer.CurrentSaved()
    +
    + def PythonIsSaved(self):
    + return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
    +
    + def LoadPrevious(self):
    + self.EndBuffering()
    + self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
    +
    + def LoadNext(self):
    + self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
    +
    + def GetBufferState(self):
    + first = self.PythonBuffer.IsFirst() and not self.Buffering
    + last = self.PythonBuffer.IsLast()
    + return not first, not last
    +
    +def _GetClassFunction(name):
    + def GetRootClass():
    + __import__("py_ext.modules." + name)
    + return getattr(modules, name).RootClass
    + return GetRootClass
    +
    +class RootClass(PythonCodeTemplate):
    +
    + # For root object, available Children Types are modules of the modules packages.
    + CTNChildrenTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
    +
    + def ConfNodePath(self):
    + return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType)
    +
    + def CTNGenerate_C(self, buildpath, locations):
    + """
    + Generate C code
    + @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    + @param locations: List of complete variables locations \
    + [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
    + "NAME" : name of the variable (generally "__IW0_1_2" style)
    + "DIR" : direction "Q","I" or "M"
    + "SIZE" : size "X", "B", "W", "D", "L"
    + "LOC" : tuple of interger for IEC location (0,1,2,...)
    + }, ...]
    + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    + """
    + current_location = self.GetCurrentLocation()
    + # define a unique name for the generated C file
    + location_str = "_".join(map(lambda x:str(x), current_location))
    +
    + ctr = self.GetCTRoot()
    + ctr.GetIECProgramsAndVariables()
    +
    + 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))
    +
    + # prepare python code
    + 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)
    + pythonfile.close()
    +
    + runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
    + runtimefile = open(runtimefile_path, 'w')
    + runtimefile.write(self.GetPythonCode())
    + runtimefile.close()
    +
    + matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
    +
    + return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
    --- /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:complexType>
    + <xsd:annotation>
    + <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
    + </xsd:annotation>
    + <xsd:sequence>
    + <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
    + </xsd:sequence>
    + </xsd:complexType>
    + </xsd:element>
    +</xsd:schema>
    --- /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
    +def myprintfunc(arg):
    + print arg
    + sys.stdout.flush()
    + return arg]]>
    +</Python>
    --- 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
    -def myprintfunc(arg):
    - print arg
    - sys.stdout.flush()
    - return arg]]>
    -</Python>
    --- /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
    +def myprintfunc(arg):
    + print arg
    + sys.stdout.flush()
    + return arg]]>
    +</Python>
    --- /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/) -->
    +
    +<svg
    + 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"
    + width="320"
    + height="250"
    + id="svg2"
    + sodipodi:version="0.32"
    + inkscape:version="0.47pre4 "
    + version="1.0"
    + sodipodi:docname="gui.svg"
    + inkscape:output_extension="org.inkscape.output.svg.inkscape">
    + <sodipodi:namedview
    + id="base"
    + pagecolor="#ffffff"
    + bordercolor="#666666"
    + borderopacity="1.0"
    + inkscape:pageopacity="0.0"
    + inkscape:pageshadow="2"
    + inkscape:zoom="1.4"
    + inkscape:cx="200.66323"
    + inkscape:cy="178.08292"
    + inkscape:document-units="px"
    + inkscape:current-layer="layer1"
    + showgrid="false"
    + inkscape:window-width="1071"
    + inkscape:window-height="805"
    + inkscape:window-x="106"
    + inkscape:window-y="16"
    + inkscape:window-maximized="0" />
    + <defs
    + id="defs4">
    + <linearGradient
    + id="linearGradient3770">
    + <stop
    + style="stop-color:#008000;stop-opacity:1;"
    + offset="0"
    + id="stop3772" />
    + <stop
    + style="stop-color:#00fb00;stop-opacity:1;"
    + offset="1"
    + id="stop3774" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3708">
    + <stop
    + style="stop-color:#d40000;stop-opacity:1;"
    + offset="0"
    + id="stop3710" />
    + <stop
    + style="stop-color:#ff5c5c;stop-opacity:1;"
    + offset="1"
    + id="stop3712" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient4202">
    + <stop
    + id="stop4204"
    + offset="0"
    + style="stop-color:#f6edda;stop-opacity:1;" />
    + <stop
    + id="stop4206"
    + offset="1"
    + style="stop-color:#e6e6e6;stop-opacity:1;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient4192">
    + <stop
    + style="stop-color:#faf4e9;stop-opacity:1;"
    + offset="0"
    + id="stop4194" />
    + <stop
    + style="stop-color:#f1f1f1;stop-opacity:1;"
    + offset="1"
    + id="stop4196" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3302">
    + <stop
    + style="stop-color:#ff0000;stop-opacity:0;"
    + offset="0"
    + id="stop3304" />
    + <stop
    + id="stop3310"
    + offset="0.43817073"
    + style="stop-color:#ff0000;stop-opacity:0.49803922;" />
    + <stop
    + style="stop-color:#ff0000;stop-opacity:1;"
    + offset="0.68879533"
    + id="stop3312" />
    + <stop
    + style="stop-color:#ff0000;stop-opacity:0;"
    + offset="1"
    + id="stop3306" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3687">
    + <stop
    + id="stop3689"
    + offset="0"
    + style="stop-color:#23d5ff;stop-opacity:1;" />
    + <stop
    + id="stop3691"
    + offset="1"
    + style="stop-color:#b1ffff;stop-opacity:1;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3679">
    + <stop
    + id="stop3681"
    + offset="0"
    + style="stop-color:#00b5ff;stop-opacity:1;" />
    + <stop
    + id="stop3683"
    + offset="1"
    + style="stop-color:#005bff;stop-opacity:1;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3659">
    + <stop
    + id="stop3661"
    + offset="0"
    + style="stop-color:#ff0030;stop-opacity:1;" />
    + <stop
    + style="stop-color:#e20000;stop-opacity:0.83211678;"
    + offset="0.60000002"
    + id="stop3669" />
    + <stop
    + id="stop3663"
    + offset="1"
    + style="stop-color:#ffffff;stop-opacity:0;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3639">
    + <stop
    + id="stop3641"
    + offset="0"
    + style="stop-color:#ffff00;stop-opacity:1;" />
    + <stop
    + style="stop-color:#8fff00;stop-opacity:0.49803922;"
    + offset="0.80000001"
    + id="stop3647" />
    + <stop
    + id="stop3643"
    + offset="1"
    + style="stop-color:#ffffff;stop-opacity:0;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3621">
    + <stop
    + id="stop3623"
    + offset="0"
    + style="stop-color:#ff8080;stop-opacity:1;" />
    + <stop
    + id="stop3625"
    + offset="1"
    + style="stop-color:#aa0000;stop-opacity:1;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3613"
    + inkscape:collect="always">
    + <stop
    + id="stop3615"
    + offset="0"
    + style="stop-color:#000000;stop-opacity:1;" />
    + <stop
    + id="stop3617"
    + offset="1"
    + style="stop-color:#000000;stop-opacity:0;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3497">
    + <stop
    + id="stop3499"
    + offset="0"
    + style="stop-color:#00cd00;stop-opacity:1;" />
    + <stop
    + id="stop3501"
    + offset="1"
    + style="stop-color:#007900;stop-opacity:1;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3453">
    + <stop
    + id="stop3455"
    + offset="0"
    + style="stop-color:#000000;stop-opacity:1;" />
    + <stop
    + id="stop3457"
    + offset="1"
    + style="stop-color:#ffffff;stop-opacity:0;" />
    + </linearGradient>
    + <linearGradient
    + id="linearGradient3173">
    + <stop
    + style="stop-color:#ffffff;stop-opacity:1;"
    + offset="0"
    + id="stop3175" />
    + <stop
    + id="stop3181"
    + offset="0.5"
    + style="stop-color:#ffffff;stop-opacity:0;" />
    + <stop
    + style="stop-color:#ff0000;stop-opacity:0;"
    + offset="1"
    + id="stop3177" />
    + </linearGradient>
    + <inkscape:perspective
    + 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="perspective10" />
    + <inkscape:perspective
    + 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" />
    + <linearGradient
    + gradientUnits="userSpaceOnUse"
    + y2="76.489952"
    + x2="96.68087"
    + y1="43.13879"
    + x1="96.68087"
    + id="linearGradient3503"
    + xlink:href="#linearGradient3497"
    + inkscape:collect="always" />
    + <linearGradient
    + gradientUnits="userSpaceOnUse"
    + y2="57.028084"
    + x2="146.58875"
    + y1="57.028084"
    + x1="56.098511"
    + id="linearGradient3619"
    + xlink:href="#linearGradient3613"
    + inkscape:collect="always" />
    + <linearGradient
    + gradientUnits="userSpaceOnUse"
    + y2="81.670944"
    + x2="102.30303"
    + y1="40.599514"
    + x1="101.45565"
    + id="linearGradient3627"
    + xlink:href="#linearGradient3621"
    + inkscape:collect="always" />
    + <linearGradient
    + gradientTransform="translate(-18,26)"
    + y2="81.670944"
    + x2="102.30303"
    + y1="40.599514"
    + x1="101.45565"
    + gradientUnits="userSpaceOnUse"
    + id="linearGradient3633"
    + xlink:href="#linearGradient3621"
    + inkscape:collect="always" />
    + <radialGradient
    + r="17.67767"
    + fy="101.69787"
    + fx="352.03818"
    + cy="101.69787"
    + cx="352.03818"
    + gradientUnits="userSpaceOnUse"
    + id="radialGradient3667"
    + xlink:href="#linearGradient3639"
    + inkscape:collect="always" />
    + <radialGradient
    + r="17.67767"
    + fy="101.69787"
    + fx="352.03818"
    + cy="101.69787"
    + cx="352.03818"
    + gradientUnits="userSpaceOnUse"
    + id="radialGradient3675"
    + xlink:href="#linearGradient3659"
    + inkscape:collect="always" />
    + <linearGradient
    + gradientTransform="translate(-1.3119965,1.110878)"
    + gradientUnits="userSpaceOnUse"
    + y2="74.0345"
    + x2="222.50246"
    + y1="102.89583"
    + x1="223.57851"
    + id="linearGradient3693"
    + xlink:href="#linearGradient3687"
    + inkscape:collect="always" />
    + <linearGradient
    + y2="116.84509"
    + x2="312.63715"
    + y1="62.306999"
    + x1="277.45764"
    + gradientUnits="userSpaceOnUse"
    + id="linearGradient3702"
    + xlink:href="#linearGradient4202"
    + inkscape:collect="always" />
    + <linearGradient
    + y2="66.89164"
    + x2="223.21674"
    + y1="102.89583"
    + x1="223.57851"
    + gradientTransform="translate(-1.3119965,1.110878)"
    + gradientUnits="userSpaceOnUse"
    + id="linearGradient3704"
    + xlink:href="#linearGradient3613"
    + inkscape:collect="always" />
    + <inkscape:perspective
    + 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" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3302"
    + id="linearGradient3308"
    + x1="255.95412"
    + y1="328.07761"
    + x2="258.63916"
    + y2="328.07761"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-25.178571,-3.0357143)" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3536"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3538"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3540"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3542"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3544"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3546"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3548"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3550"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(5.555838,16.162441)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3694"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3696"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3698"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3700"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3703"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3705"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3707"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3613"
    + id="linearGradient3709"
    + gradientUnits="userSpaceOnUse"
    + gradientTransform="translate(-381.09403,-544.64978)"
    + x1="147.86807"
    + y1="287.98224"
    + x2="147.86807"
    + y2="341.01526" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient4192"
    + id="linearGradient4200"
    + x1="9.601512"
    + y1="10.789209"
    + x2="311.62698"
    + y2="232.99521"
    + gradientUnits="userSpaceOnUse" />
    + <inkscape:perspective
    + id="perspective3695"
    + 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" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3708"
    + id="linearGradient3714"
    + x1="87.808205"
    + y1="244.84967"
    + x2="32.786144"
    + y2="103.0031"
    + gradientUnits="userSpaceOnUse" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3708"
    + id="linearGradient3722"
    + x1="73.120178"
    + y1="183.3553"
    + x2="52.375767"
    + y2="141.61852"
    + gradientUnits="userSpaceOnUse" />
    + <inkscape:perspective
    + id="perspective3732"
    + 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:perspective
    + id="perspective3757"
    + 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" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3770"
    + id="linearGradient3776"
    + x1="149.16222"
    + y1="143.01329"
    + x2="-2.1779096"
    + y2="0.84358346"
    + gradientUnits="userSpaceOnUse" />
    + <linearGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3770"
    + id="linearGradient3784"
    + x1="96.563065"
    + y1="81.798767"
    + x2="56.660259"
    + y2="47.094559"
    + gradientUnits="userSpaceOnUse" />
    + <radialGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3621"
    + id="radialGradient3792"
    + cx="352.03818"
    + cy="101.69787"
    + fx="352.03818"
    + fy="101.69787"
    + r="18.67767"
    + gradientUnits="userSpaceOnUse" />
    + <radialGradient
    + inkscape:collect="always"
    + xlink:href="#linearGradient3497"
    + id="radialGradient3800"
    + cx="352.03818"
    + cy="101.69787"
    + fx="352.03818"
    + fy="101.69787"
    + r="18.67767"
    + gradientUnits="userSpaceOnUse" />
    + </defs>
    + <metadata
    + id="metadata7">
    + <rdf:RDF>
    + <cc:Work
    + rdf:about="">
    + <dc:format>image/svg+xml</dc:format>
    + <dc:type
    + rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    + <dc:title></dc:title>
    + </cc:Work>
    + </rdf:RDF>
    + </metadata>
    + <g
    + inkscape:label="Calque 1"
    + inkscape:groupmode="layer"
    + id="layer1"
    + style="display:inline">
    + <rect
    + ry="23.307579"
    + y="11.523975"
    + x="10.336278"
    + height="220.73647"
    + width="300.55594"
    + id="rect3700"
    + 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" />
    + <g
    + transform="translate(-127.27923,-40.406102)"
    + id="g3695">
    + <rect
    + 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"
    + id="rect3677"
    + width="163.64471"
    + height="53.538086"
    + x="148.49243"
    + y="62.806999"
    + ry="5.029737" />
    + <text
    + sodipodi:linespacing="125%"
    + id="text_compteur"
    + y="102.99694"
    + x="154.30698"
    + 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
    + y="102.99694"
    + x="154.30698"
    + id="tspan3191"
    + sodipodi:role="line"
    + 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>
    + </g>
    + <g
    + id="stop_back"
    + transform="translate(-33.11078,95.2077)">
    + <path
    + sodipodi:type="star"
    + 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"
    + id="path3747"
    + sodipodi:sides="3"
    + sodipodi:cx="103.21429"
    + sodipodi:cy="127.14286"
    + sodipodi:r1="91.508057"
    + sodipodi:r2="45.754028"
    + sodipodi:arg1="0"
    + sodipodi:arg2="1.0471976"
    + inkscape:flatsided="true"
    + inkscape:rounded="0"
    + 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)" />
    + <text
    + sodipodi:linespacing="100%"
    + id="text2393"
    + y="68.857597"
    + x="151.45537"
    + 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"
    + y="68.857597"
    + x="151.45537"
    + id="tspan2395"
    + sodipodi:role="line">Start</tspan></text>
    + </g>
    + <g
    + transform="translate(-18.07106,94.06456)"
    + id="stop_sele"
    + style="fill:#aaffaa">
    + <path
    + sodipodi:type="star"
    + 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"
    + id="path3685"
    + sodipodi:sides="8"
    + sodipodi:cx="83.571426"
    + sodipodi:cy="224.28571"
    + sodipodi:r1="94.724358"
    + sodipodi:r2="87.513893"
    + sodipodi:arg1="0"
    + sodipodi:arg2="0.39269908"
    + inkscape:flatsided="true"
    + inkscape:rounded="0"
    + 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)" />
    + <text
    + sodipodi:linespacing="100%"
    + id="text2401"
    + y="66.643318"
    + x="147.74109"
    + 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"
    + y="66.643318"
    + x="147.74109"
    + id="tspan2403"
    + sodipodi:role="line">Stop</tspan></text>
    + </g>
    + <g
    + transform="matrix(2.0899173,0,0,2.0899173,-577.84265,-204.88668)"
    + id="led_start">
    + <path
    + 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:ry="17.67767"
    + sodipodi:rx="17.67767"
    + sodipodi:cy="101.69787"
    + sodipodi:cx="352.03818"
    + id="pathLed"
    + 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"
    + sodipodi:type="arc" />
    + </g>
    + <g
    + transform="matrix(2.0899173,0,0,2.0899173,-637.08625,-59.866062)"
    + id="led_stop">
    + <path
    + sodipodi:type="arc"
    + 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"
    + id="path_led"
    + sodipodi:cx="352.03818"
    + sodipodi:cy="101.69787"
    + sodipodi:rx="17.67767"
    + sodipodi:ry="17.67767"
    + 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)" />
    + </g>
    + </g>
    +</svg>
    --- /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">
    +<![CDATA[]]>
    +</Python>
    --- 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
    -def myprintfunc(arg):
    - print arg
    - sys.stdout.flush()
    - return arg]]>
    -</Python>
    --- 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/) -->
    -
    -<svg
    - 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"
    - width="320"
    - height="250"
    - id="svg2"
    - sodipodi:version="0.32"
    - inkscape:version="0.47pre4 "
    - version="1.0"
    - sodipodi:docname="gui.svg"
    - inkscape:output_extension="org.inkscape.output.svg.inkscape">
    - <sodipodi:namedview
    - id="base"
    - pagecolor="#ffffff"
    - bordercolor="#666666"
    - borderopacity="1.0"
    - inkscape:pageopacity="0.0"
    - inkscape:pageshadow="2"
    - inkscape:zoom="1.4"
    - inkscape:cx="200.66323"
    - inkscape:cy="178.08292"
    - inkscape:document-units="px"
    - inkscape:current-layer="layer1"
    - showgrid="false"
    - inkscape:window-width="1071"
    - inkscape:window-height="805"
    - inkscape:window-x="106"
    - inkscape:window-y="16"
    - inkscape:window-maximized="0" />
    - <defs
    - id="defs4">
    - <linearGradient
    - id="linearGradient3770">
    - <stop
    - style="stop-color:#008000;stop-opacity:1;"
    - offset="0"
    - id="stop3772" />
    - <stop
    - style="stop-color:#00fb00;stop-opacity:1;"
    - offset="1"
    - id="stop3774" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3708">
    - <stop
    - style="stop-color:#d40000;stop-opacity:1;"
    - offset="0"
    - id="stop3710" />
    - <stop
    - style="stop-color:#ff5c5c;stop-opacity:1;"
    - offset="1"
    - id="stop3712" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient4202">
    - <stop
    - id="stop4204"
    - offset="0"
    - style="stop-color:#f6edda;stop-opacity:1;" />
    - <stop
    - id="stop4206"
    - offset="1"
    - style="stop-color:#e6e6e6;stop-opacity:1;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient4192">
    - <stop
    - style="stop-color:#faf4e9;stop-opacity:1;"
    - offset="0"
    - id="stop4194" />
    - <stop
    - style="stop-color:#f1f1f1;stop-opacity:1;"
    - offset="1"
    - id="stop4196" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3302">
    - <stop
    - style="stop-color:#ff0000;stop-opacity:0;"
    - offset="0"
    - id="stop3304" />
    - <stop
    - id="stop3310"
    - offset="0.43817073"
    - style="stop-color:#ff0000;stop-opacity:0.49803922;" />
    - <stop
    - style="stop-color:#ff0000;stop-opacity:1;"
    - offset="0.68879533"
    - id="stop3312" />
    - <stop
    - style="stop-color:#ff0000;stop-opacity:0;"
    - offset="1"
    - id="stop3306" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3687">
    - <stop
    - id="stop3689"
    - offset="0"
    - style="stop-color:#23d5ff;stop-opacity:1;" />
    - <stop
    - id="stop3691"
    - offset="1"
    - style="stop-color:#b1ffff;stop-opacity:1;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3679">
    - <stop
    - id="stop3681"
    - offset="0"
    - style="stop-color:#00b5ff;stop-opacity:1;" />
    - <stop
    - id="stop3683"
    - offset="1"
    - style="stop-color:#005bff;stop-opacity:1;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3659">
    - <stop
    - id="stop3661"
    - offset="0"
    - style="stop-color:#ff0030;stop-opacity:1;" />
    - <stop
    - style="stop-color:#e20000;stop-opacity:0.83211678;"
    - offset="0.60000002"
    - id="stop3669" />
    - <stop
    - id="stop3663"
    - offset="1"
    - style="stop-color:#ffffff;stop-opacity:0;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3639">
    - <stop
    - id="stop3641"
    - offset="0"
    - style="stop-color:#ffff00;stop-opacity:1;" />
    - <stop
    - style="stop-color:#8fff00;stop-opacity:0.49803922;"
    - offset="0.80000001"
    - id="stop3647" />
    - <stop
    - id="stop3643"
    - offset="1"
    - style="stop-color:#ffffff;stop-opacity:0;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3621">
    - <stop
    - id="stop3623"
    - offset="0"
    - style="stop-color:#ff8080;stop-opacity:1;" />
    - <stop
    - id="stop3625"
    - offset="1"
    - style="stop-color:#aa0000;stop-opacity:1;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3613"
    - inkscape:collect="always">
    - <stop
    - id="stop3615"
    - offset="0"
    - style="stop-color:#000000;stop-opacity:1;" />
    - <stop
    - id="stop3617"
    - offset="1"
    - style="stop-color:#000000;stop-opacity:0;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3497">
    - <stop
    - id="stop3499"
    - offset="0"
    - style="stop-color:#00cd00;stop-opacity:1;" />
    - <stop
    - id="stop3501"
    - offset="1"
    - style="stop-color:#007900;stop-opacity:1;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3453">
    - <stop
    - id="stop3455"
    - offset="0"
    - style="stop-color:#000000;stop-opacity:1;" />
    - <stop
    - id="stop3457"
    - offset="1"
    - style="stop-color:#ffffff;stop-opacity:0;" />
    - </linearGradient>
    - <linearGradient
    - id="linearGradient3173">
    - <stop
    - style="stop-color:#ffffff;stop-opacity:1;"
    - offset="0"
    - id="stop3175" />
    - <stop
    - id="stop3181"
    - offset="0.5"
    - style="stop-color:#ffffff;stop-opacity:0;" />
    - <stop
    - style="stop-color:#ff0000;stop-opacity:0;"
    - offset="1"
    - id="stop3177" />
    - </linearGradient>
    - <inkscape:perspective
    - 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="perspective10" />
    - <inkscape:perspective
    - 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" />
    - <linearGradient
    - gradientUnits="userSpaceOnUse"
    - y2="76.489952"
    - x2="96.68087"
    - y1="43.13879"
    - x1="96.68087"
    - id="linearGradient3503"
    - xlink:href="#linearGradient3497"
    - inkscape:collect="always" />
    - <linearGradient
    - gradientUnits="userSpaceOnUse"
    - y2="57.028084"
    - x2="146.58875"
    - y1="57.028084"
    - x1="56.098511"
    - id="linearGradient3619"
    - xlink:href="#linearGradient3613"
    - inkscape:collect="always" />
    - <linearGradient
    - gradientUnits="userSpaceOnUse"
    - y2="81.670944"
    - x2="102.30303"
    - y1="40.599514"
    - x1="101.45565"
    - id="linearGradient3627"
    - xlink:href="#linearGradient3621"
    - inkscape:collect="always" />
    - <linearGradient
    - gradientTransform="translate(-18,26)"
    - y2="81.670944"
    - x2="102.30303"
    - y1="40.599514"
    - x1="101.45565"
    - gradientUnits="userSpaceOnUse"
    - id="linearGradient3633"
    - xlink:href="#linearGradient3621"
    - inkscape:collect="always" />
    - <radialGradient
    - r="17.67767"
    - fy="101.69787"
    - fx="352.03818"
    - cy="101.69787"
    - cx="352.03818"
    - gradientUnits="userSpaceOnUse"
    - id="radialGradient3667"
    - xlink:href="#linearGradient3639"
    - inkscape:collect="always" />
    - <radialGradient
    - r="17.67767"
    - fy="101.69787"
    - fx="352.03818"
    - cy="101.69787"
    - cx="352.03818"
    - gradientUnits="userSpaceOnUse"
    - id="radialGradient3675"
    - xlink:href="#linearGradient3659"
    - inkscape:collect="always" />
    - <linearGradient
    - gradientTransform="translate(-1.3119965,1.110878)"
    - gradientUnits="userSpaceOnUse"
    - y2="74.0345"
    - x2="222.50246"
    - y1="102.89583"
    - x1="223.57851"
    - id="linearGradient3693"
    - xlink:href="#linearGradient3687"
    - inkscape:collect="always" />
    - <linearGradient
    - y2="116.84509"
    - x2="312.63715"
    - y1="62.306999"
    - x1="277.45764"
    - gradientUnits="userSpaceOnUse"
    - id="linearGradient3702"
    - xlink:href="#linearGradient4202"
    - inkscape:collect="always" />
    - <linearGradient
    - y2="66.89164"
    - x2="223.21674"
    - y1="102.89583"
    - x1="223.57851"
    - gradientTransform="translate(-1.3119965,1.110878)"
    - gradientUnits="userSpaceOnUse"
    - id="linearGradient3704"
    - xlink:href="#linearGradient3613"
    - inkscape:collect="always" />
    - <inkscape:perspective
    - 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" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3302"
    - id="linearGradient3308"
    - x1="255.95412"
    - y1="328.07761"
    - x2="258.63916"
    - y2="328.07761"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-25.178571,-3.0357143)" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3536"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3538"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3540"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3542"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3544"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3546"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3548"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3550"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(5.555838,16.162441)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3694"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3696"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3698"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3700"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3703"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3705"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3707"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3613"
    - id="linearGradient3709"
    - gradientUnits="userSpaceOnUse"
    - gradientTransform="translate(-381.09403,-544.64978)"
    - x1="147.86807"
    - y1="287.98224"
    - x2="147.86807"
    - y2="341.01526" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient4192"
    - id="linearGradient4200"
    - x1="9.601512"
    - y1="10.789209"
    - x2="311.62698"
    - y2="232.99521"
    - gradientUnits="userSpaceOnUse" />
    - <inkscape:perspective
    - id="perspective3695"
    - 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" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3708"
    - id="linearGradient3714"
    - x1="87.808205"
    - y1="244.84967"
    - x2="32.786144"
    - y2="103.0031"
    - gradientUnits="userSpaceOnUse" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3708"
    - id="linearGradient3722"
    - x1="73.120178"
    - y1="183.3553"
    - x2="52.375767"
    - y2="141.61852"
    - gradientUnits="userSpaceOnUse" />
    - <inkscape:perspective
    - id="perspective3732"
    - 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:perspective
    - id="perspective3757"
    - 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" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3770"
    - id="linearGradient3776"
    - x1="149.16222"
    - y1="143.01329"
    - x2="-2.1779096"
    - y2="0.84358346"
    - gradientUnits="userSpaceOnUse" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3770"
    - id="linearGradient3784"
    - x1="96.563065"
    - y1="81.798767"
    - x2="56.660259"
    - y2="47.094559"
    - gradientUnits="userSpaceOnUse" />
    - <radialGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3621"
    - id="radialGradient3792"
    - cx="352.03818"
    - cy="101.69787"
    - fx="352.03818"
    - fy="101.69787"
    - r="18.67767"
    - gradientUnits="userSpaceOnUse" />
    - <radialGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3497"
    - id="radialGradient3800"
    - cx="352.03818"
    - cy="101.69787"
    - fx="352.03818"
    - fy="101.69787"
    - r="18.67767"
    - gradientUnits="userSpaceOnUse" />
    - </defs>
    - <metadata
    - id="metadata7">
    - <rdf:RDF>
    - <cc:Work
    - rdf:about="">
    - <dc:format>image/svg+xml</dc:format>
    - <dc:type
    - rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    - <dc:title></dc:title>
    - </cc:Work>
    - </rdf:RDF>
    - </metadata>
    - <g
    - inkscape:label="Calque 1"
    - inkscape:groupmode="layer"
    - id="layer1"
    - style="display:inline">
    - <rect
    - ry="23.307579"
    - y="11.523975"
    - x="10.336278"
    - height="220.73647"
    - width="300.55594"
    - id="rect3700"
    - 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" />
    - <g
    - transform="translate(-127.27923,-40.406102)"
    - id="g3695">
    - <rect
    - 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"
    - id="rect3677"
    - width="163.64471"
    - height="53.538086"
    - x="148.49243"
    - y="62.806999"
    - ry="5.029737" />
    - <text
    - sodipodi:linespacing="125%"
    - id="text_compteur"
    - y="102.99694"
    - x="154.30698"
    - 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
    - y="102.99694"
    - x="154.30698"
    - id="tspan3191"
    - sodipodi:role="line"
    - 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>
    - </g>
    - <g
    - id="stop_back"
    - transform="translate(-33.11078,95.2077)">
    - <path
    - sodipodi:type="star"
    - 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"
    - id="path3747"
    - sodipodi:sides="3"
    - sodipodi:cx="103.21429"
    - sodipodi:cy="127.14286"
    - sodipodi:r1="91.508057"
    - sodipodi:r2="45.754028"
    - sodipodi:arg1="0"
    - sodipodi:arg2="1.0471976"
    - inkscape:flatsided="true"
    - inkscape:rounded="0"
    - 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)" />
    - <text
    - sodipodi:linespacing="100%"
    - id="text2393"
    - y="68.857597"
    - x="151.45537"
    - 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"
    - y="68.857597"
    - x="151.45537"
    - id="tspan2395"
    - sodipodi:role="line">Start</tspan></text>
    - </g>
    - <g
    - transform="translate(-18.07106,94.06456)"
    - id="stop_sele"
    - style="fill:#aaffaa">
    - <path
    - sodipodi:type="star"
    - 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"
    - id="path3685"
    - sodipodi:sides="8"
    - sodipodi:cx="83.571426"
    - sodipodi:cy="224.28571"
    - sodipodi:r1="94.724358"
    - sodipodi:r2="87.513893"
    - sodipodi:arg1="0"
    - sodipodi:arg2="0.39269908"
    - inkscape:flatsided="true"
    - inkscape:rounded="0"
    - 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)" />
    - <text
    - sodipodi:linespacing="100%"
    - id="text2401"
    - y="66.643318"
    - x="147.74109"
    - 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"
    - y="66.643318"
    - x="147.74109"
    - id="tspan2403"
    - sodipodi:role="line">Stop</tspan></text>
    - </g>
    - <g
    - transform="matrix(2.0899173,0,0,2.0899173,-577.84265,-204.88668)"
    - id="led_start">
    - <path
    - 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:ry="17.67767"
    - sodipodi:rx="17.67767"
    - sodipodi:cy="101.69787"
    - sodipodi:cx="352.03818"
    - id="pathLed"
    - 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"
    - sodipodi:type="arc" />
    - </g>
    - <g
    - transform="matrix(2.0899173,0,0,2.0899173,-637.08625,-59.866062)"
    - id="led_stop">
    - <path
    - sodipodi:type="arc"
    - 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"
    - id="path_led"
    - sodipodi:cx="352.03818"
    - sodipodi:cy="101.69787"
    - sodipodi:rx="17.67767"
    - sodipodi:ry="17.67767"
    - 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)" />
    - </g>
    - </g>
    -</svg>
    --- 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">
    -<![CDATA[]]>
    -</Python>
    --- /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 @@
    +<?xml version="1.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">
    + <border>0</border>
    + <option>0</option>
    + <object class="wxSpinCtrl" name="spin_ctrl_1" base="EditSpinCtrl">
    + <range>0, 10000</range>
    + </object>
    + </object>
    + <object class="sizeritem">
    + <border>0</border>
    + <option>0</option>
    + <object class="wxCheckBox" name="checkbox_1" base="EditCheckBox">
    + <label>checkbox_1</label>
    + </object>
    + </object>
    + <object class="sizeritem">
    + <border>0</border>
    + <option>0</option>
    + <object class="wxStaticText" name="label_1" base="EditStaticText">
    + <attribute>1</attribute>
    + <label>GUI modifiée !</label>
    + </object>
    + </object>
    + </object>
    + </object>
    +</application>
    --- /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">
    +<![CDATA[]]>
    +</Python>
    --- /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">
    +<![CDATA[]]>
    +</Python>
    --- 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 @@
    -<?xml version="1.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">
    - <border>0</border>
    - <option>0</option>
    - <object class="wxSpinCtrl" name="spin_ctrl_1" base="EditSpinCtrl">
    - <range>0, 10000</range>
    - </object>
    - </object>
    - <object class="sizeritem">
    - <border>0</border>
    - <option>0</option>
    - <object class="wxCheckBox" name="checkbox_1" base="EditCheckBox">
    - <label>checkbox_1</label>
    - </object>
    - </object>
    - <object class="sizeritem">
    - <border>0</border>
    - <option>0</option>
    - <object class="wxStaticText" name="label_1" base="EditStaticText">
    - <attribute>1</attribute>
    - <label>GUI modifiée !</label>
    - </object>
    - </object>
    - </object>
    - </object>
    -</application>
    --- 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">
    -<![CDATA[]]>
    -</Python>
    --- 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">
    -<![CDATA[]]>
    -</Python>