--- a/CodeFileTreeNode.py Sun May 12 23:32:30 2013 +0200
+++ b/CodeFileTreeNode.py Mon May 13 14:31:23 2013 +0200
@@ -2,26 +2,82 @@
from xml.dom import minidom
+from xmlclass import GenerateClassesFromXSDstring, UpdateXMLClassGlobals from PLCControler import UndoBuffer
-from editors.CodeFileEditor import SECTIONS_NAMES
-CodeFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "code_file.xsd"))
+CODEFILE_XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="%(codefile_name)s"> + <xsd:element name="variables"> + <xsd:element name="variable" minOccurs="0" maxOccurs="unbounded"> + <xsd:attribute name="name" type="xsd:string" use="required"/> + <xsd:attribute name="type" type="xsd:string" use="required"/> + <xsd:attribute name="class" use="optional"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="input"/> + <xsd:enumeration value="memory"/> + <xsd:enumeration value="output"/> + <xsd:attribute name="initial" type="xsd:string" use="optional" default=""/> + <xsd:complexType name="CodeText"> + <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation> + <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/> +SECTION_TAG_ELEMENT = "<xsd:element name=\"%s\" type=\"CodeText\"/>" + CODEFILE_NAME = "CodeFile" + sections_str = {"codefile_name": self.CODEFILE_NAME} + if "includes" in self.SECTIONS_NAMES: + sections_str["includes_section"] = SECTION_TAG_ELEMENT % "includes" + sections_str["includes_section"] = "" + sections_str["sections"] = "\n".join( + [SECTION_TAG_ELEMENT % name + for name in self.SECTIONS_NAMES if name != "includes"]) + self.CodeFileClasses = GenerateClassesFromXSDstring( + CODEFILE_XSD % sections_str) filepath = self.CodeFileName()
- self.CodeFile = CodeFileClasses["CodeFile"]()
+ self.CodeFile = self.CodeFileClasses[self.CODEFILE_NAME]() if os.path.isfile(filepath):
xmlfile = open(filepath, 'r')
tree = minidom.parse(xmlfile)
for child in tree.childNodes:
- if child.nodeType == tree.ELEMENT_NODE and child.nodeName in ["CodeFile", "CFile"]:
+ if child.nodeType == tree.ELEMENT_NODE and child.nodeName in [self.CODEFILE_NAME]: self.CodeFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
self.CreateCodeFileBuffer(True)
@@ -37,7 +93,7 @@
def SetVariables(self, variables):
self.CodeFile.variables.setvariable([])
- variable = CodeFileClasses["variables_variable"]()
+ variable = self.CodeFileClasses["variables_variable"]() variable.setname(var["Name"])
variable.settype(var["Type"])
variable.setinitial(var["Initial"])
@@ -46,33 +102,21 @@
for var in self.CodeFile.variables.getvariable():
- datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Initial" : var.getinitial()})
+ datas.append({"Name" : var.getname(), + "Type" : var.gettype(), + "Initial" : var.getinitial()}) def SetTextParts(self, parts):
- for section, code_object in zip(
- [self.CodeFile.includes,
- self.CodeFile.initFunction,
- self.CodeFile.cleanUpFunction,
- self.CodeFile.retrieveFunction,
- self.CodeFile.publishFunction]):
- code_object.settext(parts[section])
+ for section in self.SECTIONS_NAMES: + section_code = parts.get(section) + if section_code is not None: + getattr(self.CodeFile, section).settext(section_code)
- for section, code_object in zip(
- [self.CodeFile.includes,
- self.CodeFile.initFunction,
- self.CodeFile.cleanUpFunction,
- self.CodeFile.retrieveFunction,
- self.CodeFile.publishFunction]):
- parts[section] = code_object.gettext()
+ return dict([(section, getattr(self.CodeFile, section).gettext()) + for section in self.SECTIONS_NAMES]) def CTNTestModified(self):
return self.ChangesToSave or not self.CodeFileIsSaved()
@@ -80,10 +124,7 @@
filepath = self.CodeFileName()
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" : "code_file.xsd"}
- text += self.CodeFile.generateXMLText("CodeFile", 0, extras)
+ text += self.CodeFile.generateXMLText(self.CODEFILE_NAME, 0) xmlfile = open(filepath,"w")
xmlfile.write(text.encode("utf-8"))
@@ -103,25 +144,33 @@
# Current Buffering Management Functions
#-------------------------------------------------------------------------------
+ def cPickle_loads(self, str_obj): + UpdateXMLClassGlobals(self.CodeFileClasses) + return cPickle.loads(str_obj) + def cPickle_dumps(self, obj): + UpdateXMLClassGlobals(self.CodeFileClasses) + return cPickle.dumps(obj) Return a copy of the codefile model
- return cPickle.loads(cPickle.dumps(model))
+ return self.cPickle_loads(self.cPickle_dumps(model)) def CreateCodeFileBuffer(self, saved):
- self.CodeFileBuffer = UndoBuffer(cPickle.dumps(self.CodeFile), saved)
+ self.CodeFileBuffer = UndoBuffer(self.cPickle_dumps(self.CodeFile), saved) def BufferCodeFile(self):
- self.CodeFileBuffer.Buffering(cPickle.dumps(self.CodeFile))
+ self.CodeFileBuffer.Buffering(self.cPickle_dumps(self.CodeFile)) def StartBuffering(self):
- self.CodeFileBuffer.Buffering(cPickle.dumps(self.CodeFile))
+ self.CodeFileBuffer.Buffering(self.cPickle_dumps(self.CodeFile)) def MarkCodeFileAsSaved(self):
@@ -133,10 +182,10 @@
- self.CodeFile = cPickle.loads(self.CodeFileBuffer.Previous())
+ self.CodeFile = self.cPickle_loads(self.CodeFileBuffer.Previous()) - self.CodeFile = cPickle.loads(self.CodeFileBuffer.Next())
+ self.CodeFile = self.cPickle_loads(self.CodeFileBuffer.Next()) def GetBufferState(self):
first = self.CodeFileBuffer.IsFirst() and not self.Buffering
--- a/c_ext/c_ext.py Sun May 12 23:32:30 2013 +0200
+++ b/c_ext/c_ext.py Mon May 13 14:31:23 2013 +0200
@@ -1,3 +1,4 @@
from CFileEditor import CFileEditor
@@ -14,8 +15,19 @@
+ CODEFILE_NAME = "CFile" + def GenerateClassesFromXSDstring(self, xsd_string): + return GenerateClassesFromXSDstring(xsd_string) --- a/editors/CodeFileEditor.py Sun May 12 23:32:30 2013 +0200
+++ b/editors/CodeFileEditor.py Mon May 13 14:31:23 2013 +0200
@@ -12,9 +12,6 @@
from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos, NAVIGATION_KEYS
from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
-SECTIONS_NAMES = ["Includes", "Globals", "Init",
- "CleanUp", "Retrieve", "Publish"]
[STC_CODE_ERROR, STC_CODE_SEARCH_RESULT,
STC_CODE_SECTION] = range(15, 18)
@@ -120,7 +117,7 @@
self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
self.SectionsComments = {}
- for section in SECTIONS_NAMES:
+ for section in self.Controler.SECTIONS_NAMES: section_comment = " %s section " % (section)
len_headers = 78 - len(section_comment)
section_comment = self.COMMENT_HEADER * (len_headers / 2) + \
@@ -131,10 +128,11 @@
"comment": section_comment,
- for i, section in enumerate(SECTIONS_NAMES):
+ for i, section in enumerate(self.Controler.SECTIONS_NAMES): section_infos = self.SectionsComments[section]
- if i + 1 < len(SECTIONS_NAMES):
- section_end = self.SectionsComments[SECTIONS_NAMES[i + 1]]["comment"]
+ if i + 1 < len(self.Controler.SECTIONS_NAMES): + section_end = self.SectionsComments[ + self.Controler.SECTIONS_NAMES[i + 1]]["comment"] section_infos["pattern"] = re.compile(
@@ -203,7 +201,7 @@
parts = self.Controler.GetTextParts()
- for section in SECTIONS_NAMES:
+ for section in self.Controler.SECTIONS_NAMES: section_comments = self.SectionsComments[section]
text += section_comments["comment"]
@@ -246,7 +244,7 @@
for line in xrange(self.GetLineCount()):
self.SetLineState(line, 0)
- for section in SECTIONS_NAMES:
+ for section in self.Controler.SECTIONS_NAMES: section_comments = self.SectionsComments[section]
start_pos = text.find(section_comments["comment"])
end_pos = start_pos + len(section_comments["comment"])
@@ -263,7 +261,7 @@
- for section in SECTIONS_NAMES:
+ for section in self.Controler.SECTIONS_NAMES: section_comments = self.SectionsComments[section]
result = section_comments["pattern"].search(text)
@@ -276,14 +274,26 @@
- current_pos = self.GetSelection()[0]
+ current_pos = self.GetCurrentPos() + selected = self.GetSelection() + text_selected = selected[0] != selected[1] + # Disable to type any character in section header lines if (self.GetLineState(self.LineFromPosition(current_pos)) and
key not in NAVIGATION_KEYS + [
+ # Disable to delete line between code and header lines + elif (self.GetCurLine()[0].strip() != "" and not text_selected and + (key == wx.WXK_BACK and + self.GetLineState(self.LineFromPosition(max(0, current_pos - 1))) or + key in [wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE] and + self.GetLineState(self.LineFromPosition(min(len(self.GetText()), current_pos + 1))))): elif key == 32 and event.ControlDown():
pos = self.GetCurrentPos()
@@ -435,6 +445,7 @@
self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
+ self.ParentWindow.RefreshEditMenu() --- a/py_ext/PythonFileCTNMixin.py Sun May 12 23:32:30 2013 +0200
+++ b/py_ext/PythonFileCTNMixin.py Mon May 13 14:31:23 2013 +0200
@@ -3,7 +3,7 @@
from PythonEditor import PythonEditor
from xml.dom import minidom
+from xmlclass import GenerateClassesFromXSD from CodeFileTreeNode import CodeFile
@@ -12,6 +12,13 @@
class PythonFileCTNMixin(CodeFile):
+ CODEFILE_NAME = "PyFile" EditorType = PythonEditor
@@ -39,53 +46,35 @@
def PythonFileName(self):
return os.path.join(self.CTNPath(), "py_ext.xml")
- def GetPythonCode(self):
- 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 python mixin confnode\n\n"
+ def GetSectionsCode(self):
- text += "## User includes\n"
- text += self.CodeFile.includes.gettext().strip()
- text += "## User variables reference\n"
+ # Generate Beremiz python runtime variables code config = self.GetCTRoot().GetProjectConfigNames()[0]
for variable in self.CodeFile.variables.variable:
global_name = "%s_%s" % (config.upper(), variable.getname().upper())
- text += "# global_var:%s python_var:%s type:%s initial:%s\n" % (
+ variables_str += "# global_var:%s python_var:%s type:%s initial:%s\n" % ( str(variable.getinitial()))
- # Adding user global variables and routines
- text += "## User internal user variables and routines\n"
- text += self.CodeFile.globals.gettext().strip()
+ "variables": variables_str, + "globals": self.CodeFile.globals.gettext().strip() - # Adding Beremiz confnode functions
- text += "## Beremiz confnode functions\n"
- for func, args, return_code, code_object in [
- ("__init_", "*args, **kwargs",
- "return 0", self.CodeFile.initFunction),
- ("__cleanup_", "", "", self.CodeFile.cleanUpFunction),
- ("__retrieve_", "", "", self.CodeFile.retrieveFunction),
- ("__publish_", "", "", self.CodeFile.publishFunction),]:
- text += "def %s%s(%s):\n" % (func, location_str, args)
- lines = code_object.gettext().strip().splitlines()
- if len(lines) > 0 or return_code != "":
- text += " " + line + "\n"
- text += " " + return_code + "\n"
+ # Generate Beremiz python runtime functions code + for section in self.SECTIONS_NAMES: + if section != "globals": + code_object = getattr(self.CodeFile, section) + lines = code_object.gettext().strip().splitlines() + section_str += " " + line + "\n" + sections_code[section] = section_str --- a/py_ext/py_ext.py Sun May 12 23:32:30 2013 +0200
+++ b/py_ext/py_ext.py Mon May 13 14:31:23 2013 +0200
@@ -38,9 +38,35 @@
# define a unique name for the generated C file
location_str = "_".join(map(lambda x:str(x), current_location))
+ sections_code = self.GetSectionsCode() + text = "## Code generated by Beremiz python mixin confnode\n\n" + text += "## User variables reference\n" + text += sections_code["variables"] + # Adding user global variables and routines + text += "## User internal user variables and routines\n" + text += sections_code["globals"] + # Adding Beremiz python runtime functions + text += "## Beremiz python runtime functions\n" + for section in self.SECTIONS_NAMES: + if section != "globals": + code_object = getattr(self.CodeFile, section) + text += "def _runtime_%s_%s():\n" % (location_str, section) + section_code = sections_code.get(section) runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
runtimefile = open(runtimefile_path, 'w')
- runtimefile.write(self.GetPythonCode())
+ runtimefile.write(text) return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
--- a/wxglade_hmi/wxglade_hmi.py Sun May 12 23:32:30 2013 +0200
+++ b/wxglade_hmi/wxglade_hmi.py Mon May 13 14:31:23 2013 +0200
@@ -76,33 +76,59 @@
runtimefile.write(hmipyfile.read())
- runtimefile.write(self.GetPythonCode())
-def _runtime_%(location)s_start():
- wx.MessageBox(_("Please stop PLC to close"))
-def _runtime_%(location)s_stop():
-""" % {"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: """
+ sections_code = self.GetSectionsCode() + runtimefile.write("## User variables reference\n" + + sections_code["variables"] + "\n") + # Adding user global variables and routines + runtimefile.write("## User internal user variables and routines\n" + + sections_code["globals"] + "\n") + for section in ["init", "cleanup"]: + if not sections_code[section]: + sections_code = " pass" + "location": location_str, + "declare_hmi": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())), + "global_hmi": ",".join(hmi_frames.keys()), + "init_hmi": "\n".join(map(lambda x: """ %(name)s = %(class)s(None)
%(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
""" % {"name": x[0], "class": x[1]},
- "cleanup": "\n ".join(map(lambda x:"if %s is not None: %s.Destroy()" % (x,x), hmi_frames.keys()))})
+ "cleanup_hmi": "\n ".join(map(lambda x:"if %s is not None: %s.Destroy()" % (x,x), hmi_frames.keys()))}) +def _runtime_%(location)s_init(): +def _runtime_%(location)s_cleanup(): +def _runtime_%(location)s_start(): + wx.MessageBox(_("Please stop PLC to close")) +def _runtime_%(location)s_stop(): return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
--- a/xmlclass/__init__.py Sun May 12 23:32:30 2013 +0200
+++ b/xmlclass/__init__.py Mon May 13 14:31:23 2013 +0200
@@ -24,5 +24,5 @@
-from xmlclass import ClassFactory, GenerateClasses, GetAttributeValue, time_model, CreateNode, NodeSetAttr, NodeRenameAttr
+from xmlclass import ClassFactory, GenerateClasses, GetAttributeValue, time_model, CreateNode, NodeSetAttr, NodeRenameAttr, UpdateXMLClassGlobals from xsdschema import XSDClassFactory, GenerateClassesFromXSD, GenerateClassesFromXSDstring
--- a/xmlclass/xmlclass.py Sun May 12 23:32:30 2013 +0200
+++ b/xmlclass/xmlclass.py Mon May 13 14:31:23 2013 +0200
@@ -1857,9 +1857,11 @@
def GenerateClasses(factory):
ComputedClasses = factory.CreateClasses()
if factory.FileName is not None and len(ComputedClasses) == 1:
- globals().update(ComputedClasses[factory.FileName])
+ UpdateXMLClassGlobals(ComputedClasses[factory.FileName]) return ComputedClasses[factory.FileName]
- globals().update(ComputedClasses)
+ UpdateXMLClassGlobals(ComputedClasses) +def UpdateXMLClassGlobals(classes): + globals().update(classes)