# HG changeset patch # User Andrey Skvortsov # Date 1502742435 -10800 # Node ID 7e61baa047f07011d4fd80b771d25aab30d116e6 # Parent c02818d7e29f5e7e5ef39f7c4f983319aac4d9f4 clean-up: fix PEP8 E302 expected 2 blank lines, found 1 diff -r c02818d7e29f -r 7e61baa047f0 Beremiz.py --- a/Beremiz.py Mon Aug 14 22:30:41 2017 +0300 +++ b/Beremiz.py Mon Aug 14 23:27:15 2017 +0300 @@ -31,6 +31,7 @@ import __builtin__ import util.paths as paths + class BeremizIDELauncher: def __init__(self): self.updateinfo_url = None diff -r c02818d7e29f -r 7e61baa047f0 BeremizIDE.py --- a/BeremizIDE.py Mon Aug 14 22:30:41 2017 +0300 +++ b/BeremizIDE.py Mon Aug 14 23:27:15 2017 +0300 @@ -37,6 +37,7 @@ beremiz_dir = paths.AbsDir(__file__) + def Bpath(*args): return os.path.join(beremiz_dir,*args) @@ -88,6 +89,8 @@ MainThread = currentThread().ident REFRESH_PERIOD = 0.1 from time import time as gettime + + class LogPseudoFile: """ Base class for file like objects to facilitate StdOut for the Shell.""" def __init__(self, output, risecall): @@ -213,6 +216,7 @@ EncodeFileSystemPath, DecodeFileSystemPath from util.BitmapLibrary import GetBitmap + class Beremiz(IDEFrame): def _init_utils(self): @@ -1086,6 +1090,7 @@ Max_Traceback_List_Size = 20 + def Display_Exception_Dialog(e_type, e_value, e_tb, bug_report_path): trcbck_lst = [] for i,line in enumerate(traceback.extract_tb(e_tb)): @@ -1124,6 +1129,7 @@ return res + def get_last_traceback(tb): while tb.tb_next: tb = tb.tb_next @@ -1136,6 +1142,7 @@ ignored_exceptions = [] # a problem with a line in a module is only reported once per session + def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]): def save_bug_report(e_type, e_value, e_traceback, bug_report_path,date): diff -r c02818d7e29f -r 7e61baa047f0 Beremiz_service.py --- a/Beremiz_service.py Mon Aug 14 22:30:41 2017 +0300 +++ b/Beremiz_service.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ import getopt from threading import Thread + def usage(): print """ Usage of Beremiz PLC execution service :\n @@ -116,9 +117,11 @@ if __name__ == '__main__': __builtin__.__dict__['_'] = lambda x: x + def Bpath(*args): return os.path.join(beremiz_dir,*args) + def SetupI18n(): # Import module for internationalization import gettext @@ -379,6 +382,7 @@ if not os.path.isdir(WorkingDir): os.mkdir(WorkingDir) + def default_evaluator(tocall, *args, **kwargs): try: res=(tocall(*args,**kwargs), None) @@ -386,6 +390,7 @@ res=(None, sys.exc_info()) return res + class Server(): def __init__(self, servicename, ip_addr, port, workdir, argv, autostart=False, @@ -528,6 +533,8 @@ # Exception hooks s import threading import traceback + + def LogException(*exp): if pyroserver.plcobj is not None: pyroserver.plcobj.LogMessage(0,'\n'.join(traceback.format_exception(*exp))) @@ -535,6 +542,8 @@ traceback.print_exception(*exp) sys.excepthook = LogException + + def installThreadExcepthook(): init_old = threading.Thread.__init__ def init(self, *args, **kwargs): diff -r c02818d7e29f -r 7e61baa047f0 CodeFileTreeNode.py --- a/CodeFileTreeNode.py Mon Aug 14 22:30:41 2017 +0300 +++ b/CodeFileTreeNode.py Mon Aug 14 23:27:15 2017 +0300 @@ -82,6 +82,7 @@ SECTION_TAG_ELEMENT = "" + class CodeFile: CODEFILE_NAME = "CodeFile" diff -r c02818d7e29f -r 7e61baa047f0 ConfigTreeNode.py --- a/ConfigTreeNode.py Mon Aug 14 22:30:41 2017 +0300 +++ b/ConfigTreeNode.py Mon Aug 14 23:27:15 2017 +0300 @@ -57,6 +57,7 @@ NameTypeSeparator = '@' XSDSchemaErrorMessage = _("{a1} XML file doesn't follow XSD schema at line {a2}:\n{a3}") + class ConfigTreeNode: """ This class is the one that define confnodes. diff -r c02818d7e29f -r 7e61baa047f0 IDEFrame.py --- a/IDEFrame.py Mon Aug 14 22:30:41 2017 +0300 +++ b/IDEFrame.py Mon Aug 14 23:27:15 2017 +0300 @@ -193,19 +193,24 @@ import base64 + def EncodeFileSystemPath(path, use_base64=True): path = path.encode(sys.getfilesystemencoding()) if use_base64: return base64.encodestring(path) return path + def DecodeFileSystemPath(path, is_base64=True): if is_base64: path = base64.decodestring(path) return unicode(path, sys.getfilesystemencoding()) -# Compatibility function for wx versions < 2.6 + def AppendMenu(parent, help, id, kind, text): + """ + Compatibility function for wx versions < 2.6 + """ if wx.VERSION >= (2, 6, 0): parent.Append(help=help, id=id, kind=kind, text=text) else: @@ -215,6 +220,7 @@ POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES ] = range(10) + def GetShortcutKeyCallbackFunction(viewer_function): def ShortcutKeyFunction(self, event): control = self.FindFocus() @@ -226,6 +232,7 @@ control.ProcessEvent(event) return ShortcutKeyFunction + def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None): def DeleteElementFunction(self, selected): name = self.ProjectTree.GetItemText(selected) @@ -245,6 +252,7 @@ TAB_BORDER = 7 NOTEBOOK_BORDER = 2 + def SimplifyTabLayout(tabs, rect): for tab in tabs: if tab["pos"][0] == rect.x: @@ -278,6 +286,7 @@ return True return False + def ComputeTabsLayout(tabs, rect): if len(tabs) == 0: return tabs @@ -323,6 +332,7 @@ UNEDITABLE_NAMES_DICT = dict([(_(name), name) for name in UNEDITABLE_NAMES]) + class IDEFrame(wx.Frame): # Compatibility function for wx versions < 2.6 @@ -2549,6 +2559,7 @@ UPPER_DIV = lambda x, y: (x / y) + {True : 0, False : 1}[(x % y) == 0] + class GraphicPrintout(wx.Printout): def __init__(self, viewer, page_size, margins, preview = False): wx.Printout.__init__(self) diff -r c02818d7e29f -r 7e61baa047f0 NativeLib.py --- a/NativeLib.py Mon Aug 14 22:30:41 2017 +0300 +++ b/NativeLib.py Mon Aug 14 23:27:15 2017 +0300 @@ -27,6 +27,7 @@ import util.paths as paths from POULibrary import POULibrary + class NativeLibrary(POULibrary): def GetLibraryPath(self): return paths.AbsNeighbourFile(__file__, "NativeLib.xml") diff -r c02818d7e29f -r 7e61baa047f0 PLCControler.py --- a/PLCControler.py Mon Aug 14 22:30:41 2017 +0300 +++ b/PLCControler.py Mon Aug 14 23:27:15 2017 +0300 @@ -94,6 +94,7 @@ ScriptDirectory = paths.AbsDir(__file__) + def GetUneditableNames(): _ = lambda x:x return [_("User-defined POUs"), _("Functions"), _("Function Blocks"), @@ -108,6 +109,7 @@ # Helper object for loading library in xslt stylesheets #------------------------------------------------------------------------------- + class LibraryResolver(etree.Resolver): def __init__(self, controller, debug=False): @@ -136,6 +138,7 @@ _StringValue = lambda x: x _BoolValue = lambda x: x in ["true", "0"] + def _translate_args(translations, args): return [translate(arg[0]) if len(arg) > 0 else None for translate, arg in @@ -145,6 +148,7 @@ # Helpers object for generating pou var list #------------------------------------------------------------------------------- + class _VariableInfos(object): __slots__ = ["Name", "Class", "Option", "Location", "InitialValue", "Edit", "Documentation", "Type", "Tree", "Number"] @@ -154,6 +158,7 @@ def copy(self): return _VariableInfos(*[getattr(self, attr) for attr in self.__slots__]) + class VariablesInfosFactory: def __init__(self, variables): @@ -194,6 +199,7 @@ # Helpers object for generating pou variable instance list #------------------------------------------------------------------------------- + def class_extraction(value): class_type = { "configuration": ITEM_CONFIGURATION, @@ -214,6 +220,7 @@ return None + class _VariablesTreeItemInfos(object): __slots__ = ["name", "var_class", "type", "edit", "debug", "variables"] def __init__(self, *args): @@ -222,6 +229,7 @@ def copy(self): return _VariableTreeItem(*[getattr(self, attr) for attr in self.__slots__]) + class VariablesTreeInfosFactory: def __init__(self): @@ -247,6 +255,7 @@ # Helpers object for generating instances path list #------------------------------------------------------------------------------- + class InstancesPathFactory: def __init__(self, instances): @@ -259,6 +268,7 @@ # Helpers object for generating instance tagname #------------------------------------------------------------------------------- + class InstanceTagName: def __init__(self, controller): @@ -355,6 +365,7 @@ _ConnectionLinkInfos = namedtuple("ConnectionLinkInfos", ["refLocalId", "formalParameter", "points"]) + class _ActionInfos(object): __slots__ = ["qualifier", "type", "value", "duration", "indicator"] def __init__(self, *args): @@ -363,6 +374,7 @@ def copy(self): return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__]) + class BlockInstanceFactory: def __init__(self, block_instances): @@ -438,13 +450,16 @@ # Length of the buffer UNDO_BUFFER_LENGTH = 20 -""" -Class implementing a buffer of changes made on the current editing model -""" + class UndoBuffer: - - # Constructor initialising buffer + """ + Class implementing a buffer of changes made on the current editing model + """ + def __init__(self, currentstate, issaved = False): + """ + Constructor initialising buffer + """ self.Buffer = [] self.CurrentIndex = -1 self.MinIndex = -1 @@ -466,8 +481,11 @@ else: self.LastSave = -1 - # Add a new state in buffer + def Buffering(self, currentstate): + """ + Add a new state in buffer + """ self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH self.Buffer[self.CurrentIndex] = currentstate # Actualising buffer limits @@ -479,8 +497,11 @@ self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH self.MinIndex = max(self.MinIndex, 0) - # Return current state of buffer + def Current(self): + """ + Return current state of buffer + """ return self.Buffer[self.CurrentIndex] # Change current state to previous in buffer and return new current state @@ -518,10 +539,11 @@ # Controler for PLCOpenEditor #------------------------------------------------------------------------------- -""" -Class which controls the operations made on the plcopen model and answers to view requests -""" + class PLCControler: + """ + Class which controls the operations made on the plcopen model and answers to view requests + """ # Create a new PLCControler def __init__(self): diff -r c02818d7e29f -r 7e61baa047f0 PLCGenerator.py --- a/PLCGenerator.py Mon Aug 14 22:30:41 2017 +0300 +++ b/PLCGenerator.py Mon Aug 14 23:27:15 2017 +0300 @@ -45,8 +45,9 @@ "VAR_INOUT": "var_inout", } -# Helper function for reindenting text + def ReIndentText(text, nb_spaces): + """ Helper function for reindenting text """ compute = "" lines = text.splitlines() if len(lines) > 0: @@ -67,6 +68,7 @@ compute += "\n" return compute + def SortInstances(a, b): ax, ay = int(a.getx()), int(a.gety()) bx, by = int(b.getx()), int(b.gety()) @@ -75,8 +77,9 @@ else: return cmp(ay, by) -# Helper for emulate join on element list + def JoinList(separator, mylist): + """ Helper for emulate join on element list """ if len(mylist) > 0 : return reduce(lambda x, y: x + separator + y, mylist) else : @@ -500,6 +503,7 @@ TransitionObjClass = PLCOpenParser.GetElementClass("transition", "transitions") ActionObjClass = PLCOpenParser.GetElementClass("action", "actions") + class PouProgramGenerator: # Create a new POU program generator @@ -1658,6 +1662,7 @@ program += [("END_%s\n\n" % self.Type, ())] return program + def GenerateCurrentProgram(controler, project, errors, warnings): generator = ProgramGenerator(controler, project, errors, warnings) generator.GenerateProgram() diff -r c02818d7e29f -r 7e61baa047f0 PLCOpenEditor.py --- a/PLCOpenEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/PLCOpenEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -94,6 +94,7 @@ [ID_PLCOPENEDITORFILEMENUGENERATE, ] = [wx.NewId() for _init_coll_FileMenu_Items in range(1)] + class PLCOpenEditor(IDEFrame): # Compatibility function for wx versions < 2.6 @@ -403,6 +404,7 @@ Max_Traceback_List_Size = 20 + def Display_Exception_Dialog(e_type,e_value,e_tb): trcbck_lst = [] for i,line in enumerate(traceback.extract_tb(e_tb)): @@ -441,11 +443,13 @@ return res + def Display_Error_Dialog(e_value): message = wx.MessageDialog(None, str(e_value), _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() message.Destroy() + def get_last_traceback(tb): while tb.tb_next: tb = tb.tb_next @@ -458,6 +462,7 @@ ignored_exceptions = [] # a problem with a line in a module is only reported once per session + def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]): def handle_exception(e_type, e_value, e_traceback): diff -r c02818d7e29f -r 7e61baa047f0 POULibrary.py --- a/POULibrary.py Mon Aug 14 22:30:41 2017 +0300 +++ b/POULibrary.py Mon Aug 14 23:27:15 2017 +0300 @@ -24,6 +24,7 @@ from weakref import ref + class POULibrary: def __init__(self, CTR, LibName, TypeStack): from PLCControler import PLCControler diff -r c02818d7e29f -r 7e61baa047f0 ProjectController.py --- a/ProjectController.py Mon Aug 14 22:30:41 2017 +0300 +++ b/ProjectController.py Mon Aug 14 23:27:15 2017 +0300 @@ -67,6 +67,7 @@ ITEM_CONFNODE = 25 + def ExtractChildrenTypesFromCatalog(catalog): children_types = [] for n,d,h,c in catalog: @@ -76,6 +77,7 @@ children_types.append((n, GetClassImporter(c), d)) return children_types + def ExtractMenuItemsFromCatalog(catalog): menu_items = [] for n,d,h,c in catalog: @@ -86,9 +88,11 @@ menu_items.append((n, d, h, children)) return menu_items + def GetAddMenuItems(): return ExtractMenuItemsFromCatalog(features.catalog) + class Iec2CSettings(): def __init__(self): self.iec2c = None @@ -170,6 +174,7 @@ iec2c_cfg = Iec2CSettings() + class ProjectController(ConfigTreeNode, PLCControler): """ This class define Root object of the confnode tree. diff -r c02818d7e29f -r 7e61baa047f0 c_ext/CFileEditor.py --- a/c_ext/CFileEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/c_ext/CFileEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -27,6 +27,7 @@ from controls.CustomStyledTextCtrl import faces from editors.CodeFileEditor import CodeFileEditor, CodeEditor + class CppEditor(CodeEditor): KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", @@ -57,6 +58,7 @@ # CFileEditor Main Frame Class #------------------------------------------------------------------------------- + class CFileEditor(CodeFileEditor): CONFNODEEDITOR_TABS = [ diff -r c02818d7e29f -r 7e61baa047f0 c_ext/c_ext.py --- a/c_ext/c_ext.py Mon Aug 14 22:30:41 2017 +0300 +++ b/c_ext/c_ext.py Mon Aug 14 23:27:15 2017 +0300 @@ -27,6 +27,7 @@ from CFileEditor import CFileEditor from CodeFileTreeNode import CodeFile + class CFile(CodeFile): XSD = """ diff -r c02818d7e29f -r 7e61baa047f0 canfestival/NetworkEditor.py --- a/canfestival/NetworkEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/canfestival/NetworkEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -45,6 +45,7 @@ ID_NETWORKEDITORADDMENUMAPVARIABLE, ID_NETWORKEDITORADDMENUUSERTYPE, ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)] + class NetworkEditor(ConfTreeNodeEditor, NetworkEditorTemplate): ID = ID_NETWORKEDITOR diff -r c02818d7e29f -r 7e61baa047f0 canfestival/SlaveEditor.py --- a/canfestival/SlaveEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/canfestival/SlaveEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -38,6 +38,7 @@ ID_SLAVEEDITORADDMENUMAPVARIABLE, ID_SLAVEEDITORADDMENUUSERTYPE, ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)] + class SlaveEditor(ConfTreeNodeEditor, NodeEditorTemplate): CONFNODEEDITOR_TABS = [ @@ -97,6 +98,7 @@ self.ParentWindow.RefreshEditMenu() self.ParentWindow.RefreshPageTitles() + class MasterViewer(SlaveEditor): SHOW_BASE_PARAMS = False SHOW_PARAMS = False diff -r c02818d7e29f -r 7e61baa047f0 canfestival/canfestival.py --- a/canfestival/canfestival.py Mon Aug 14 22:30:41 2017 +0300 +++ b/canfestival/canfestival.py Mon Aug 14 23:27:15 2017 +0300 @@ -60,6 +60,7 @@ # Location Tree Helper #-------------------------------------------------- + def GetSlaveLocationTree(slave_node, current_location, name): entries = [] for index, subindex, size, entry_name in slave_node.GetMapVariableList(): @@ -86,6 +87,7 @@ # SLAVE #-------------------------------------------------- + class _SlaveCTN(NodeManager): XSD = """ @@ -246,6 +248,7 @@ # MASTER #-------------------------------------------------- + class MiniNodeManager(NodeManager): def __init__(self, parent, filepath, fullname): @@ -273,6 +276,7 @@ ConfNodeMethods = [] + class _NodeManager(NodeManager): def __init__(self, parent, *args, **kwargs): @@ -288,6 +292,7 @@ def GetCurrentNodeID(self): return self.Parent.CanFestivalNode.getNodeId() + class _NodeListCTN(NodeList): XSD = """ @@ -459,6 +464,7 @@ def GetBufferState(self): return self.Manager.GetCurrentBufferState() + class RootClass: XSD = """ diff -r c02818d7e29f -r 7e61baa047f0 canfestival/config_utils.py --- a/canfestival/config_utils.py Mon Aug 14 22:30:41 2017 +0300 +++ b/canfestival/config_utils.py Mon Aug 14 23:27:15 2017 +0300 @@ -50,6 +50,7 @@ # Specific exception for PDO mapping errors #------------------------------------------------------------------------------- + class PDOmappingException(Exception): pass @@ -137,6 +138,7 @@ dcfdata += [LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4)] return "".join(dcfdata), len(dcfdata) + class ConciseDCFGenerator: def __init__(self, nodelist, nodename): @@ -592,6 +594,7 @@ # 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. @@ -613,6 +616,7 @@ pointers.update(LocalODPointers(locations, current_location, masternode)) return masternode,pointers + def LocalODPointers(locations, current_location, slave): IECLocations = {} pointers = {} diff -r c02818d7e29f -r 7e61baa047f0 connectors/PYRO/__init__.py --- a/connectors/PYRO/__init__.py Mon Aug 14 22:30:41 2017 +0300 +++ b/connectors/PYRO/__init__.py Mon Aug 14 23:27:15 2017 +0300 @@ -38,6 +38,7 @@ # for connectors that do not support DNS-SD, this attribute can be omitted # or set to an empty list. + def PYRO_connector_factory(uri, confnodesroot): """ This returns the connector to Pyro style PLCobject diff -r c02818d7e29f -r 7e61baa047f0 connectors/WAMP/__init__.py --- a/connectors/WAMP/__init__.py Mon Aug 14 22:30:41 2017 +0300 +++ b/connectors/WAMP/__init__.py Mon Aug 14 23:27:15 2017 +0300 @@ -38,6 +38,7 @@ _WampConnection = None _WampSessionEvent = Event() + class WampSession(wamp.ApplicationSession): def onJoin(self, details): global _WampSession, _WampSessionEvent @@ -56,6 +57,7 @@ "GetPLCstatus" : ("Broken",None), "RemoteExec" : (-1, "RemoteExec script failed!")} + def WAMP_connector_factory(uri, confnodesroot): """ WAMP://127.0.0.1:12345/path#realm#ID diff -r c02818d7e29f -r 7e61baa047f0 controls/CustomEditableListBox.py --- a/controls/CustomEditableListBox.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/CustomEditableListBox.py Mon Aug 14 23:27:15 2017 +0300 @@ -25,6 +25,7 @@ import wx import wx.gizmos + class CustomEditableListBox(wx.gizmos.EditableListBox): def __init__(self, *args, **kwargs): diff -r c02818d7e29f -r 7e61baa047f0 controls/CustomGrid.py --- a/controls/CustomGrid.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/CustomGrid.py Mon Aug 14 23:27:15 2017 +0300 @@ -25,6 +25,7 @@ import wx import wx.grid + class CustomGrid(wx.grid.Grid): def __init__(self, *args, **kwargs): diff -r c02818d7e29f -r 7e61baa047f0 controls/CustomStyledTextCtrl.py --- a/controls/CustomStyledTextCtrl.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/CustomStyledTextCtrl.py Mon Aug 14 23:27:15 2017 +0300 @@ -58,6 +58,7 @@ wx.WXK_NUMPAD_PAGEDOWN, wx.WXK_NUMPAD_END] + def GetCursorPos(old, new): if old == "": return 0 @@ -81,6 +82,7 @@ else: return None + class CustomStyledTextCtrl(wx.stc.StyledTextCtrl): def __init__(self, *args, **kwargs): diff -r c02818d7e29f -r 7e61baa047f0 controls/CustomTable.py --- a/controls/CustomTable.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/CustomTable.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,6 +30,7 @@ else: ROW_HEIGHT = 28 + class CustomTable(wx.grid.PyGridTableBase): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/CustomToolTip.py --- a/controls/CustomToolTip.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/CustomToolTip.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,11 +34,11 @@ # Custom ToolTip #------------------------------------------------------------------------------- -""" -Class that implements a custom tool tip -""" class CustomToolTip(wx.PopupWindow): + """ + Class that implements a custom tool tip + """ def __init__(self, parent, tip, restricted=True): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/CustomTree.py --- a/controls/CustomTree.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/CustomTree.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,6 +30,7 @@ # Customize CustomTreeItem for adding icon on item left CT.GenericTreeItem._ExtraImage = None + def SetExtraImage(self, image): self._type = (1 if image is not None else 0) self._ExtraImage = image @@ -37,12 +38,15 @@ CT.GenericTreeItem.SetExtraImage = SetExtraImage _DefaultGetCurrentCheckedImage = CT.GenericTreeItem.GetCurrentCheckedImage + + def GetCurrentCheckedImage(self): if self._ExtraImage is not None: return self._ExtraImage return _DefaultGetCurrentCheckedImage(self) CT.GenericTreeItem.GetCurrentCheckedImage = GetCurrentCheckedImage + class CustomTree(CT.CustomTreeCtrl): def __init__(self, *args, **kwargs): diff -r c02818d7e29f -r 7e61baa047f0 controls/DebugVariablePanel/DebugVariableGraphicViewer.py --- a/controls/DebugVariablePanel/DebugVariableGraphicViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/DebugVariablePanel/DebugVariableGraphicViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -67,6 +67,7 @@ # Debug Variable Graphic Viewer Helpers #------------------------------------------------------------------------------- + def merge_ranges(ranges): """ Merge variables data range in a list to return a range of minimal min range @@ -107,12 +108,12 @@ # Debug Variable Graphic Viewer Drop Target #------------------------------------------------------------------------------- -""" -Class that implements a custom drop target class for Debug Variable Graphic -Viewer -""" class DebugVariableGraphicDropTarget(wx.TextDropTarget): + """ + Class that implements a custom drop target class for Debug Variable Graphic + Viewer + """ def __init__(self, parent, window): """ @@ -238,11 +239,11 @@ # Debug Variable Graphic Viewer Class #------------------------------------------------------------------------------- -""" -Class that implements a Viewer that display variable values as a graphs -""" class DebugVariableGraphicViewer(DebugVariableViewer, FigureCanvas): + """ + Class that implements a Viewer that display variable values as a graphs + """ def __init__(self, parent, window, items, graph_type): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/DebugVariablePanel/DebugVariableItem.py --- a/controls/DebugVariablePanel/DebugVariableItem.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/DebugVariablePanel/DebugVariableItem.py Mon Aug 14 23:27:15 2017 +0300 @@ -38,12 +38,12 @@ # Debug Variable Item Class #------------------------------------------------------------------------------- -""" -Class that implements an element that consumes debug values for PLC variable and -stores received values for displaying them in graphic panel or table -""" class DebugVariableItem(DebugDataConsumer): + """ + Class that implements an element that consumes debug values for PLC variable and + stores received values for displaying them in graphic panel or table + """ def __init__(self, parent, variable, store_data=False): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/DebugVariablePanel/DebugVariablePanel.py --- a/controls/DebugVariablePanel/DebugVariablePanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/DebugVariablePanel/DebugVariablePanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -58,10 +58,12 @@ # Scrollbar increment in pixel SCROLLBAR_UNIT = 10 + def compute_mask(x, y): return [(xp if xp == yp else "*") for xp, yp in zip(x, y)] + def NextTick(variables): next_tick = None for item, data in variables: @@ -78,12 +80,12 @@ # Debug Variable Graphic Panel Drop Target #------------------------------------------------------------------------------- -""" -Class that implements a custom drop target class for Debug Variable Graphic -Panel -""" class DebugVariableDropTarget(wx.TextDropTarget): + """ + Class that implements a custom drop target class for Debug Variable Graphic + Panel + """ def __init__(self, window): """ @@ -173,11 +175,11 @@ # Debug Variable Graphic Panel Class #------------------------------------------------------------------------------- -""" -Class that implements a Viewer that display variable values as a graphs -""" class DebugVariablePanel(wx.Panel, DebugViewer): + """ + Class that implements a Viewer that display variable values as a graphs + """ def __init__(self, parent, producer, window): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/DebugVariablePanel/DebugVariableTextViewer.py --- a/controls/DebugVariablePanel/DebugVariableTextViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/DebugVariablePanel/DebugVariableTextViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,11 +34,11 @@ # Debug Variable Text Viewer Drop Target #------------------------------------------------------------------------------- -""" -Class that implements a custom drop target class for Debug Variable Text Viewer -""" class DebugVariableTextDropTarget(wx.TextDropTarget): + """ + Class that implements a custom drop target class for Debug Variable Text Viewer + """ def __init__(self, parent, window): """ @@ -144,11 +144,10 @@ # Debug Variable Text Viewer Class #------------------------------------------------------------------------------- -""" -Class that implements a Viewer that display variable values as a text -""" - class DebugVariableTextViewer(DebugVariableViewer, wx.Panel): + """ + Class that implements a Viewer that display variable values as a text + """ def __init__(self, parent, window, items=[]): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/DebugVariablePanel/DebugVariableViewer.py --- a/controls/DebugVariablePanel/DebugVariableViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/DebugVariablePanel/DebugVariableViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -50,12 +50,12 @@ # Base Debug Variable Viewer Class #------------------------------------------------------------------------------- -""" -Class that implements a generic viewer that display a list of variable values -This class has to be inherited to effectively display variable values -""" class DebugVariableViewer: + """ + Class that implements a generic viewer that display a list of variable values + This class has to be inherited to effectively display variable values + """ def __init__(self, window, items=[]): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/DebugVariablePanel/GraphButton.py --- a/controls/DebugVariablePanel/GraphButton.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/DebugVariablePanel/GraphButton.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,11 +30,11 @@ # Custom button for Graphic Viewer Class #------------------------------------------------------------------------------- -""" -Class that implements a custom button for graphic Viewer -""" class GraphButton(): + """ + Class that implements a custom button for graphic Viewer + """ def __init__(self, x, y, bitmap, callback): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/DurationCellEditor.py --- a/controls/DurationCellEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/DurationCellEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -26,6 +26,7 @@ from dialogs.DurationEditorDialog import DurationEditorDialog + class DurationCellControl(wx.PyControl): ''' @@ -94,6 +95,7 @@ def SetFocus(self): self.Duration.SetFocus() + class DurationCellEditor(wx.grid.PyGridCellEditor): ''' Grid cell editor that uses DurationCellControl to display an edit button. diff -r c02818d7e29f -r 7e61baa047f0 controls/EnhancedStatusBar.py --- a/controls/EnhancedStatusBar.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/EnhancedStatusBar.py Mon Aug 14 23:27:15 2017 +0300 @@ -80,6 +80,7 @@ def __init__(self, widget, pos, horizontalalignment=ESB_ALIGN_CENTER_HORIZONTAL, verticalalignment=ESB_ALIGN_CENTER_VERTICAL): self.__dict__.update( locals() ) + class EnhancedStatusBar(wx.StatusBar): def __init__(self, parent, id=wx.ID_ANY, style=wx.ST_SIZEGRIP, diff -r c02818d7e29f -r 7e61baa047f0 controls/FolderTree.py --- a/controls/FolderTree.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/FolderTree.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,6 +30,7 @@ DRIVE, FOLDER, FILE = range(3) + def sort_folder(x, y): if x[1] == y[1]: return cmp(x[0], y[0]) @@ -38,6 +39,7 @@ else: return 1 + def splitpath(path): head, tail = os.path.split(path) if head == "": @@ -46,6 +48,7 @@ return splitpath(head) return splitpath(head) + [tail] + class FolderTree(wx.Panel): def __init__(self, parent, folder, filter=None, editable=True): diff -r c02818d7e29f -r 7e61baa047f0 controls/LibraryPanel.py --- a/controls/LibraryPanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/LibraryPanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,14 +34,14 @@ # Library Panel #------------------------------------------------------------------------------- -""" -Class that implements a panel displaying a tree containing an hierarchical list -of functions and function blocks available in project an a search control for -quickly find one functions or function blocks in this list and a text control -displaying informations about selected functions or function blocks -""" class LibraryPanel(wx.Panel): + """ + Class that implements a panel displaying a tree containing an hierarchical list + of functions and function blocks available in project an a search control for + quickly find one functions or function blocks in this list and a text control + displaying informations about selected functions or function blocks + """ def __init__(self, parent, enable_drag=False): """ diff -r c02818d7e29f -r 7e61baa047f0 controls/LocationCellEditor.py --- a/controls/LocationCellEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/LocationCellEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -26,6 +26,7 @@ from dialogs.BrowseLocationsDialog import BrowseLocationsDialog + class LocationCellControl(wx.PyControl): ''' @@ -133,6 +134,7 @@ def SetFocus(self): self.Location.SetFocus() + class LocationCellEditor(wx.grid.PyGridCellEditor): ''' Grid cell editor that uses LocationCellControl to display a browse button. diff -r c02818d7e29f -r 7e61baa047f0 controls/LogViewer.py --- a/controls/LogViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/LogViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -37,6 +37,7 @@ THUMB_SIZE_RATIO = 1. / 8. + def ArrowPoints(direction, width, height, xoffset, yoffset): if direction == wx.TOP: return [wx.Point(xoffset + 1, yoffset + height - 2), @@ -47,6 +48,7 @@ wx.Point(xoffset + width / 2, yoffset - 2), wx.Point(xoffset + width - 1, yoffset - height + 1)] + class LogScrollBar(wx.Panel): def __init__(self, parent, size): @@ -179,6 +181,7 @@ BUTTON_SIZE = (70, 15) + class LogButton(): def __init__(self, label, callback): @@ -223,6 +226,7 @@ DATE_INFO_SIZE = 10 MESSAGE_INFO_SIZE = 18 + class LogMessage: def __init__(self, tv_sec, tv_nsec, level, level_bitmap, msg): @@ -281,6 +285,7 @@ (_("1m"), MINUTE), (_("1s"), SECOND)] + class LogViewer(DebugViewer, wx.Panel): def __init__(self, parent, window): diff -r c02818d7e29f -r 7e61baa047f0 controls/PouInstanceVariablesPanel.py --- a/controls/PouInstanceVariablesPanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/PouInstanceVariablesPanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -31,10 +31,12 @@ # Customize CustomTreeItem for adding icon on item right CT.GenericTreeItem._rightimages = [] + def SetRightImages(self, images): self._rightimages = images CT.GenericTreeItem.SetRightImages = SetRightImages + def GetRightImages(self): return self._rightimages CT.GenericTreeItem.GetRightImages = GetRightImages @@ -112,6 +114,7 @@ from PLCControler import ITEMS_VARIABLE, ITEM_CONFIGURATION, ITEM_RESOURCE, ITEM_POU, ITEM_TRANSITION, ITEM_ACTION from util.BitmapLibrary import GetBitmap + class PouInstanceVariablesPanel(wx.Panel): def __init__(self, parent, window, controller, debug): diff -r c02818d7e29f -r 7e61baa047f0 controls/ProjectPropertiesPanel.py --- a/controls/ProjectPropertiesPanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/ProjectPropertiesPanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -39,6 +39,7 @@ # Project Properties Panel #------------------------------------------------------------------------------- + class ProjectPropertiesPanel(wx.Notebook): def AddSizerParams(self, parent, sizer, params): diff -r c02818d7e29f -r 7e61baa047f0 controls/SearchResultPanel.py --- a/controls/SearchResultPanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/SearchResultPanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -31,6 +31,7 @@ from PLCControler import * from util.BitmapLibrary import GetBitmap + def GenerateName(infos): if infos[0] in ["input", "output", "value"]: return "%s %d:" % (infos[0], infos[1]) @@ -48,6 +49,7 @@ ID_SEARCHRESULTPANELSEARCHRESULTSTREE, ID_SEARCHRESULTPANELRESETBUTTON, ] = [wx.NewId() for _init_ctrls in range(4)] + class SearchResultPanel(wx.Panel): if wx.VERSION < (2, 6, 0): diff -r c02818d7e29f -r 7e61baa047f0 controls/TextCtrlAutoComplete.py --- a/controls/TextCtrlAutoComplete.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/TextCtrlAutoComplete.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,6 +34,7 @@ LISTBOX_BORDER_HEIGHT = 4 LISTBOX_INTERVAL_HEIGHT = 6 + class PopupWithListbox(wx.PopupWindow): def __init__(self, parent, choices=[]): @@ -105,6 +106,7 @@ self.ListBox.HitTest(wx.Point(event.GetX(), event.GetY()))) event.Skip() + class TextCtrlAutoComplete(wx.TextCtrl): def __init__ (self, parent, choices=None, dropDownClick=True, diff -r c02818d7e29f -r 7e61baa047f0 controls/VariablePanel.py --- a/controls/VariablePanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/controls/VariablePanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -47,12 +47,14 @@ POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES ] = range(10) + def GetVariableTableColnames(location): _ = lambda x : x if location: return ["#", _("Name"), _("Class"), _("Type"), _("Location"), _("Initial Value"), _("Option"), _("Documentation")] return ["#", _("Name"), _("Class"), _("Type"), _("Initial Value"), _("Option"), _("Documentation")] + def GetOptions(constant=True, retain=True, non_retain=True): _ = lambda x : x options = [""] @@ -65,6 +67,7 @@ return options OPTIONS_DICT = dict([(_(option), option) for option in GetOptions()]) + def GetFilterChoiceTransfer(): _ = lambda x : x return {_("All"): _("All"), _("Interface"): _("Interface"), @@ -90,6 +93,7 @@ # Variables Panel Table #------------------------------------------------------------------------------- + class VariableTable(CustomTable): """ @@ -227,6 +231,7 @@ # Variable Panel Drop Target #------------------------------------------------------------------------------- + class VariableDropTarget(wx.TextDropTarget): ''' This allows dragging a variable location from somewhere to the Location @@ -407,6 +412,7 @@ # Variable Panel #------------------------------------------------------------------------------- + class VariablePanel(wx.Panel): def __init__(self, parent, window, controler, element_type, debug=False): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/AboutDialog.py --- a/dialogs/AboutDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/AboutDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -175,6 +175,7 @@ #---------------------------------------------------------------------- + def ShowAboutDialog(parent, info): if os.name == "nt": AboutDialog(parent, info) diff -r c02818d7e29f -r 7e61baa047f0 dialogs/ActionBlockDialog.py --- a/dialogs/ActionBlockDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/ActionBlockDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,10 +34,12 @@ # Helpers #------------------------------------------------------------------------------- + def GetActionTableColnames(): _ = lambda x: x return [_("Qualifier"), _("Duration"), _("Type"), _("Value"), _("Indicator")] + def GetTypeList(): _ = lambda x: x return [_("Action"), _("Variable"), _("Inline")] @@ -46,6 +48,7 @@ # Action Table #------------------------------------------------------------------------------- + class ActionTable(CustomTable): def GetValue(self, row, col): @@ -115,6 +118,7 @@ # Action Block Dialog #------------------------------------------------------------------------------- + class ActionBlockDialog(wx.Dialog): def __init__(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/ArrayTypeDialog.py --- a/dialogs/ArrayTypeDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/ArrayTypeDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -38,6 +38,7 @@ # Array Type Dialog #------------------------------------------------------------------------------- + class ArrayTypeDialog(wx.Dialog): def __init__(self, parent, datatypes, infos): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/BlockPreviewDialog.py --- a/dialogs/BlockPreviewDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/BlockPreviewDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,12 +32,12 @@ # Dialog with preview for graphic block #------------------------------------------------------------------------------- -""" -Class that implements a generic dialog containing a preview panel for displaying -graphic created by dialog -""" class BlockPreviewDialog(wx.Dialog): + """ + Class that implements a generic dialog containing a preview panel for displaying + graphic created by dialog + """ def __init__(self, parent, controller, tagname, title): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/BrowseLocationsDialog.py --- a/dialogs/BrowseLocationsDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/BrowseLocationsDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -35,6 +35,7 @@ # Helpers #------------------------------------------------------------------------------- + def GetDirFilterChoiceOptions(): _ = lambda x : x return [(_("All"), [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]), @@ -43,6 +44,7 @@ (_("Memory"), [LOCATION_VAR_MEMORY])] DIRFILTERCHOICE_OPTIONS = dict([(_(option), filter) for option, filter in GetDirFilterChoiceOptions()]) + def GetTypeFilterChoiceOptions(): _ = lambda x : x return [_("All"), @@ -59,6 +61,7 @@ # Browse Locations Dialog #------------------------------------------------------------------------------- + class BrowseLocationsDialog(wx.Dialog): def __init__(self, parent, var_type, controller): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/ConnectionDialog.py --- a/dialogs/ConnectionDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/ConnectionDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -33,12 +33,12 @@ # Set Connection Parameters Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters of a connection graphic -element -""" class ConnectionDialog(BlockPreviewDialog): + """ + Class that implements a dialog for defining parameters of a connection graphic + element + """ def __init__(self, parent, controller, tagname, apply_button=False): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/DiscoveryDialog.py --- a/dialogs/DiscoveryDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/DiscoveryDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,6 +32,7 @@ service_type = '_PYRO._tcp.local.' + class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): def __init__(self, parent, id, name, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0): @@ -43,6 +44,7 @@ ID_DISCOVERYDIALOGLOCALBUTTON, ID_DISCOVERYDIALOGIPBUTTON, ] = [wx.NewId() for _init_ctrls in range(6)] + class DiscoveryDialog(wx.Dialog, listmix.ColumnSorterMixin): def _init_coll_MainSizer_Items(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/DurationEditorDialog.py --- a/dialogs/DurationEditorDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/DurationEditorDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -53,6 +53,7 @@ # Edit Duration Value Dialog #------------------------------------------------------------------------------- + class DurationEditorDialog(wx.Dialog): def __init__(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/FBDBlockDialog.py --- a/dialogs/FBDBlockDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/FBDBlockDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -35,6 +35,7 @@ # Helpers #------------------------------------------------------------------------------- + def GetBlockTypeDefaultNameModel(blocktype): return re.compile("%s[0-9]+" % blocktype if blocktype is not None else ".*") @@ -42,12 +43,12 @@ # Set Block Parameters Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters of a FBD block graphic -element -""" class FBDBlockDialog(BlockPreviewDialog): + """ + Class that implements a dialog for defining parameters of a FBD block graphic + element + """ def __init__(self, parent, controller, tagname): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/FBDVariableDialog.py --- a/dialogs/FBDVariableDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/FBDVariableDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -45,12 +45,12 @@ # Set Variable Parameters Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters of a FBD variable graphic -element -""" class FBDVariableDialog(BlockPreviewDialog): + """ + Class that implements a dialog for defining parameters of a FBD variable graphic + element + """ def __init__(self, parent, controller, tagname, exclude_input=False): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/FindInPouDialog.py --- a/dialogs/FindInPouDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/FindInPouDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -26,6 +26,7 @@ import wx from plcopen.plcopen import * + class FindInPouDialog(wx.Dialog): def _init_icon(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/ForceVariableDialog.py --- a/dialogs/ForceVariableDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/ForceVariableDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -36,6 +36,7 @@ "D" : ["DINT", "UDINT", "REAL", "DWORD"], "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} + def gen_get_function(f): def get_function(v): try: @@ -44,6 +45,7 @@ return None return get_function + def gen_get_string(delimiter): STRING_MODEL = re.compile("%(delimiter)s([^%(delimiter)s]*)%(delimiter)s$" % {"delimiter": delimiter}) def get_string(v): @@ -68,6 +70,7 @@ IEC_DATETIME_MODEL = re.compile("(?:(?:DT|DATE_AND_TIME)#)?([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$") IEC_TIMEOFDAY_MODEL = re.compile("(?:(?:TOD|TIME_OF_DAY)#)?([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$") + def gettime(v): result = IEC_TIME_MODEL.match(v.upper()) if result is not None: @@ -91,6 +94,7 @@ else: return None + def getdate(v): result = IEC_DATE_MODEL.match(v.upper()) if result is not None: @@ -104,6 +108,7 @@ else: return None + def getdatetime(v): result = IEC_DATETIME_MODEL.match(v.upper()) if result is not None: @@ -117,6 +122,7 @@ else: return None + def gettimeofday(v): result = IEC_TIMEOFDAY_MODEL.match(v.upper()) if result is not None: @@ -156,6 +162,7 @@ # Force Variable Dialog #------------------------------------------------------------------------------- + class ForceVariableDialog(wx.TextEntryDialog): def __init__(self, parent, iec_type, defaultValue=""): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/LDElementDialog.py --- a/dialogs/LDElementDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/LDElementDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -35,12 +35,12 @@ # Set Ladder Element Parmeters Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters of a LD contact or coil -graphic element -""" class LDElementDialog(BlockPreviewDialog): + """ + Class that implements a dialog for defining parameters of a LD contact or coil + graphic element + """ def __init__(self, parent, controller, tagname, type): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/LDPowerRailDialog.py --- a/dialogs/LDPowerRailDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/LDPowerRailDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -33,13 +33,12 @@ # Set Ladder Power Rail Parameters Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters of a power rail graphic -element -""" class LDPowerRailDialog(BlockPreviewDialog): - + """ + Class that implements a dialog for defining parameters of a power rail graphic + element + """ def __init__(self, parent, controller, tagname): """ Constructor diff -r c02818d7e29f -r 7e61baa047f0 dialogs/PouActionDialog.py --- a/dialogs/PouActionDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/PouActionDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -27,11 +27,13 @@ from plcopen.structures import TestIdentifier, IEC_KEYWORDS + def GetActionLanguages(): _ = lambda x : x return [_("IL"), _("ST"), _("LD"), _("FBD")] ACTION_LANGUAGES_DICT = dict([(_(language), language) for language in GetActionLanguages()]) + class PouActionDialog(wx.Dialog): def __init__(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/PouDialog.py --- a/dialogs/PouDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/PouDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -27,15 +27,18 @@ from plcopen.structures import TestIdentifier, IEC_KEYWORDS + def GetPouTypes(): _ = lambda x : x return [_("function"), _("functionBlock"), _("program")] POU_TYPES_DICT = dict([(_(pou_type), pou_type) for pou_type in GetPouTypes()]) + def GetPouLanguages(): _ = lambda x : x return [_("IL"), _("ST"), _("LD"), _("FBD"), _("SFC")] + class PouDialog(wx.Dialog): POU_LANGUAGES = GetPouLanguages() diff -r c02818d7e29f -r 7e61baa047f0 dialogs/PouNameDialog.py --- a/dialogs/PouNameDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/PouNameDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ # POU Name Dialog #------------------------------------------------------------------------------- + class PouNameDialog(wx.TextEntryDialog): def __init__(self, parent, message, caption = "Please enter text", defaultValue = "", diff -r c02818d7e29f -r 7e61baa047f0 dialogs/PouTransitionDialog.py --- a/dialogs/PouTransitionDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/PouTransitionDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -31,11 +31,13 @@ # POU Transition Dialog #------------------------------------------------------------------------------- + def GetTransitionLanguages(): _ = lambda x : x return [_("IL"), _("ST"), _("LD"), _("FBD")] TRANSITION_LANGUAGES_DICT = dict([(_(language), language) for language in GetTransitionLanguages()]) + class PouTransitionDialog(wx.Dialog): def __init__(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/ProjectDialog.py --- a/dialogs/ProjectDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/ProjectDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -27,6 +27,7 @@ from controls.ProjectPropertiesPanel import ProjectPropertiesPanel + class ProjectDialog(wx.Dialog): def __init__(self, parent, enable_required=True): diff -r c02818d7e29f -r 7e61baa047f0 dialogs/SFCDivergenceDialog.py --- a/dialogs/SFCDivergenceDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/SFCDivergenceDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,12 +34,12 @@ # Create New Divergence Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters for creating a new -divergence graphic element -""" class SFCDivergenceDialog(BlockPreviewDialog): + """ + Class that implements a dialog for defining parameters for creating a new + divergence graphic element + """ def __init__(self, parent, controller, tagname, poss_div_types = None): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/SFCStepDialog.py --- a/dialogs/SFCStepDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/SFCStepDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,12 +32,12 @@ # Set SFC Step Parameters Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters of a SFC step graphic -element -""" class SFCStepDialog(BlockPreviewDialog): + """ + Class that implements a dialog for defining parameters of a SFC step graphic + element + """ def __init__(self, parent, controller, tagname, initial=False): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/SFCStepNameDialog.py --- a/dialogs/SFCStepNameDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/SFCStepNameDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ # Edit Step Name Dialog #------------------------------------------------------------------------------- + class SFCStepNameDialog(wx.TextEntryDialog): def __init__(self, parent, message, caption = "Please enter text", defaultValue = "", diff -r c02818d7e29f -r 7e61baa047f0 dialogs/SFCTransitionDialog.py --- a/dialogs/SFCTransitionDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/SFCTransitionDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,12 +32,12 @@ # Set Transition Parameters Dialog #------------------------------------------------------------------------------- -""" -Class that implements a dialog for defining parameters of a transition graphic -element -""" class SFCTransitionDialog(BlockPreviewDialog): + """ + Class that implements a dialog for defining parameters of a transition graphic + element + """ def __init__(self, parent, controller, tagname, connection=True): """ diff -r c02818d7e29f -r 7e61baa047f0 dialogs/SearchInProjectDialog.py --- a/dialogs/SearchInProjectDialog.py Mon Aug 14 22:30:41 2017 +0300 +++ b/dialogs/SearchInProjectDialog.py Mon Aug 14 23:27:15 2017 +0300 @@ -31,6 +31,7 @@ # Search In Project Dialog #------------------------------------------------------------------------------- + def GetElementsChoices(): _ = lambda x: x return [("datatype", _("Data Type")), @@ -39,6 +40,7 @@ ("program", _("Program")), ("configuration", _("Configuration"))] + class SearchInProjectDialog(wx.Dialog): def __init__(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 docutil/dochtml.py --- a/docutil/dochtml.py Mon Aug 14 22:30:41 2017 +0300 +++ b/docutil/dochtml.py Mon Aug 14 23:27:15 2017 +0300 @@ -29,6 +29,7 @@ HtmlFrameOpened = [] + def OpenHtmlFrame(self, title, file, size): if title not in HtmlFrameOpened: HtmlFrameOpened.append(title) @@ -41,12 +42,14 @@ [ID_HTMLFRAME, ID_HTMLFRAMEHTMLCONTENT] = [wx.NewId() for _init_ctrls in range(2)] EVT_HTML_URL_CLICK = wx.NewId() + class HtmlWindowUrlClick(wx.PyEvent): def __init__(self, linkinfo): wx.PyEvent.__init__(self) self.SetEventType(EVT_HTML_URL_CLICK) self.linkinfo = (linkinfo.GetHref(), linkinfo.GetTarget()) + class UrlClickHtmlWindow(wx.html.HtmlWindow): """ HTML window that generates and OnLinkClicked event. @@ -61,6 +64,7 @@ else: wx.html.HtmlWindow.Bind(event, handler, source=source, id=id, id2=id2) + class HtmlFrame(wx.Frame): def _init_ctrls(self, prnt): wx.Frame.__init__(self, id=ID_HTMLFRAME, name='HtmlFrame', diff -r c02818d7e29f -r 7e61baa047f0 docutil/docpdf.py --- a/docutil/docpdf.py Mon Aug 14 22:30:41 2017 +0300 +++ b/docutil/docpdf.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ readerexepath = None + def get_acroversion(): " Return version of Adobe Acrobat executable or None" import _winreg @@ -45,12 +46,14 @@ pass return None + def open_win_pdf(readerexepath, pdffile, pagenum = None): if pagenum != None : os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", "/A", "page=%d=OpenActions" % pagenum, '"%s"' % pdffile) else: os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", '"%s"' % pdffile) + def open_lin_pdf(readerexepath, pdffile, pagenum = None): if pagenum == None : os.system("%s -remote DS301 %s &" % (readerexepath, pdffile)) @@ -58,6 +61,7 @@ print "Open pdf %s at page %d" % (pdffile, pagenum) os.system("%s -remote DS301 %s %d &" % (readerexepath, pdffile, pagenum)) + def open_pdf(pdffile, pagenum = None): if wx.Platform == '__WXMSW__' : try: diff -r c02818d7e29f -r 7e61baa047f0 docutil/docsvg.py --- a/docutil/docsvg.py Mon Aug 14 22:30:41 2017 +0300 +++ b/docutil/docsvg.py Mon Aug 14 23:27:15 2017 +0300 @@ -26,6 +26,7 @@ import os import subprocess + def get_inkscape_path(): """ Return the Inkscape path """ import _winreg @@ -34,6 +35,7 @@ svgexepath = svgexepath.replace('"%1"', '') return svgexepath.replace('"', '') + def open_win_svg(svgexepath, svgfile): """ Open Inkscape on Windows platform """ popenargs = [svgexepath] @@ -41,11 +43,13 @@ popenargs.append(svgfile) subprocess.Popen(popenargs).pid + def open_lin_svg(svgexepath, svgfile): """ Open Inkscape on Linux platform """ if os.path.isfile("/usr/bin/inkscape"): os.system("%s %s &" % (svgexepath , svgfile)) + def open_svg(svgfile): """ Generic function to open SVG file """ if wx.Platform == '__WXMSW__' : diff -r c02818d7e29f -r 7e61baa047f0 editors/CodeFileEditor.py --- a/editors/CodeFileEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/CodeFileEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -48,6 +48,7 @@ EDGE_COLUMN = 80 + class CodeEditor(CustomStyledTextCtrl): KEYWORDS = [] diff -r c02818d7e29f -r 7e61baa047f0 editors/ConfTreeNodeEditor.py --- a/editors/ConfTreeNodeEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/ConfTreeNodeEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -53,6 +53,7 @@ SCROLLBAR_UNIT = 10 + class GenBitmapTextButton(wx.lib.buttons.GenBitmapTextButton): def _GetLabelSize(self): """ used internally """ @@ -124,6 +125,7 @@ style, name) + class ConfTreeNodeEditor(EditorPanel): SHOW_BASE_PARAMS = True diff -r c02818d7e29f -r 7e61baa047f0 editors/DataTypeEditor.py --- a/editors/DataTypeEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/DataTypeEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -42,13 +42,16 @@ DIMENSION_MODEL = re.compile("([0-9]+)\.\.([0-9]+)$") + def AppendMenu(parent, help, id, kind, text): parent.Append(help=help, id=id, kind=kind, text=text) + def GetElementsTableColnames(): _ = lambda x : x return ["#", _("Name"), _("Type"), _("Initial Value")] + def GetDatatypeTypes(): _ = lambda x : x return [_("Directly"), _("Subrange"), _("Enumerated"), _("Array"), _("Structure")] @@ -58,6 +61,7 @@ # Structure Elements Table #------------------------------------------------------------------------------- + class ElementsTable(CustomTable): """ @@ -137,6 +141,7 @@ # Datatype Editor class #------------------------------------------------------------------------------- + class DataTypeEditor(EditorPanel): def _init_Editor(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 editors/DebugViewer.py --- a/editors/DebugViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/DebugViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,12 +34,12 @@ # Debug Viewer Class #------------------------------------------------------------------------------- -""" -Class that implements common behavior of every viewers able to display debug -values -""" class DebugViewer: + """ + Class that implements common behavior of every viewers able to display debug + values + """ def __init__(self, producer, debug, subscribe_tick=True): """ diff -r c02818d7e29f -r 7e61baa047f0 editors/EditorPanel.py --- a/editors/EditorPanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/EditorPanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -26,6 +26,7 @@ from controls import VariablePanel + class EditorPanel(wx.SplitterWindow): VARIABLE_PANEL_TYPE = None diff -r c02818d7e29f -r 7e61baa047f0 editors/FileManagementPanel.py --- a/editors/FileManagementPanel.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/FileManagementPanel.py Mon Aug 14 23:27:15 2017 +0300 @@ -34,6 +34,7 @@ FILTER = _("All files (*.*)|*.*|CSV files (*.csv)|*.csv") + class FileManagementPanel(EditorPanel): def _init_Editor(self, parent): diff -r c02818d7e29f -r 7e61baa047f0 editors/IECCodeViewer.py --- a/editors/IECCodeViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/IECCodeViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -25,6 +25,7 @@ from editors.TextViewer import TextViewer from plcopen.plcopen import TestTextElement + class IECCodeViewer(TextViewer): def __del__(self): diff -r c02818d7e29f -r 7e61baa047f0 editors/LDViewer.py --- a/editors/LDViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/LDViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ from Viewer import * + def ExtractNextBlocks(block, block_list): current_list = [block] while len(current_list) > 0: @@ -50,6 +51,7 @@ next_list.append(next) current_list = next_list + def CalcBranchSize(elements, stops): branch_size = 0 stop_list = stops @@ -91,6 +93,7 @@ return 1 return branch_size + def RemoveElement(remove, element_tree): if remove in element_tree and element_tree[remove]: for child in element_tree[remove]["children"]: @@ -99,6 +102,7 @@ element_tree.pop(remove) ## element_tree[remove] = None + def GenerateTree(element, element_tree, stop_list): if element in element_tree: connectors = element.GetConnectors() @@ -128,6 +132,7 @@ element_tree[next] = {"parents":[element], "children":[], "weight":None} GenerateTree(next, element_tree, stop_list) + def CalcWeight(element, element_tree): weight = 0 parts = None @@ -160,11 +165,10 @@ #------------------------------------------------------------------------------- -""" -Class derived from Viewer class that implements a Viewer of Ladder Diagram -""" - class LD_Viewer(Viewer): + """ + Class derived from Viewer class that implements a Viewer of Ladder Diagram + """ def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""): Viewer.__init__(self, parent, tagname, window, controler, debug, instancepath) diff -r c02818d7e29f -r 7e61baa047f0 editors/ProjectNodeEditor.py --- a/editors/ProjectNodeEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/ProjectNodeEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ from EditorPanel import EditorPanel from ConfTreeNodeEditor import ConfTreeNodeEditor + class ProjectNodeEditor(ConfTreeNodeEditor): SHOW_BASE_PARAMS = False diff -r c02818d7e29f -r 7e61baa047f0 editors/ResourceEditor.py --- a/editors/ResourceEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/ResourceEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -39,6 +39,7 @@ [ID_CONFIGURATIONEDITOR, ] = [wx.NewId() for _init_ctrls in range(1)] + class ConfigurationEditor(EditorPanel): ID = ID_CONFIGURATIONEDITOR @@ -67,6 +68,7 @@ _ = lambda x : x return [_("Name"), _("Triggering"), _("Single"), _("Interval"), _("Priority")] + def GetTaskTriggeringOptions(): _ = lambda x : x return [_("Interrupt"), _("Cyclic")] @@ -74,6 +76,7 @@ SingleCellEditor = lambda *x : wx.grid.GridCellChoiceEditor() + def CheckSingle(single, varlist): return single in varlist @@ -82,6 +85,7 @@ _ = lambda x : x return [_("Name"), _("Type"), _("Task")] + class ResourceTable(CustomTable): """ diff -r c02818d7e29f -r 7e61baa047f0 editors/TextViewer.py --- a/editors/TextViewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/TextViewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -67,9 +67,11 @@ SEARCH_RESULT_HIGHLIGHT: STC_PLC_SEARCH_RESULT, } + def LineStartswith(line, symbols): return reduce(lambda x, y: x or y, map(lambda x: line.startswith(x), symbols), False) + class TextViewer(EditorPanel): ID = ID_TEXTVIEWER diff -r c02818d7e29f -r 7e61baa047f0 editors/Viewer.py --- a/editors/Viewer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/editors/Viewer.py Mon Aug 14 23:27:15 2017 +0300 @@ -46,6 +46,7 @@ CURSORS = None SFC_Objects = (SFC_Step, SFC_ActionBlock, SFC_Transition, SFC_Divergence, SFC_Jump) + def ResetCursors(): global CURSORS if CURSORS == None: @@ -56,6 +57,7 @@ wx.StockCursor(wx.CURSOR_SIZEWE), wx.StockCursor(wx.CURSOR_SIZENS)] + def AppendMenu(parent, help, id, kind, text): if wx.VERSION >= (2, 6, 0): parent.Append(help=help, id=id, kind=kind, text=text) @@ -83,6 +85,7 @@ MAX_ZOOMIN = 7 ZOOM_FACTORS = [math.sqrt(2) ** x for x in xrange(-6, MAX_ZOOMIN)] + def GetVariableCreationFunction(variable_type): def variableCreationFunction(viewer, id, specific_values): return FBD_Variable(viewer, variable_type, @@ -92,15 +95,18 @@ specific_values.execution_order) return variableCreationFunction + def GetConnectorCreationFunction(connector_type): def connectorCreationFunction(viewer, id, specific_values): return FBD_Connector(viewer, connector_type, specific_values.name, id) return connectorCreationFunction + def commentCreationFunction(viewer, id, specific_values): return Comment(viewer, specific_values.content, id) + def GetPowerRailCreationFunction(powerrail_type): def powerRailCreationFunction(viewer, id, specific_values): return LD_PowerRail(viewer, powerrail_type, id, @@ -114,6 +120,7 @@ (False, "rising"): CONTACT_RISING, (False, "falling"): CONTACT_FALLING} + def contactCreationFunction(viewer, id, specific_values): contact_type = CONTACT_TYPES.get((NEGATED_VALUE(specific_values.negated), MODIFIER_VALUE(specific_values.edge)), @@ -126,6 +133,7 @@ (False, "rising", "none"): COIL_RISING, (False, "falling", "none"): COIL_FALLING} + def coilCreationFunction(viewer, id, specific_values): coil_type = COIL_TYPES.get((NEGATED_VALUE(specific_values.negated), MODIFIER_VALUE(specific_values.edge), @@ -133,6 +141,7 @@ COIL_NORMAL) return LD_Coil(viewer, coil_type, specific_values.name, id) + def stepCreationFunction(viewer, id, specific_values): step = SFC_Step(viewer, specific_values.name, specific_values.initial, id) @@ -142,6 +151,7 @@ connector.SetPosition(wx.Point(*specific_values.action.position)) return step + def transitionCreationFunction(viewer, id, specific_values): transition = SFC_Transition(viewer, specific_values.condition_type, specific_values.condition, @@ -151,15 +161,18 @@ divergence_types = [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE, SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE] + def GetDivergenceCreationFunction(divergence_type): def divergenceCreationFunction(viewer, id, specific_values): return SFC_Divergence(viewer, divergence_type, specific_values.connectors, id) return divergenceCreationFunction + def jumpCreationFunction(viewer, id, specific_values): return SFC_Jump(viewer, specific_values.target, id) + def actionBlockCreationFunction(viewer, id, specific_values): return SFC_ActionBlock(viewer, specific_values.actions, id) @@ -184,6 +197,7 @@ "actionBlock": actionBlockCreationFunction, } + def sort_blocks(block_infos1, block_infos2): x1, y1 = block_infos1[0].GetPosition() x2, y2 = block_infos2[0].GetPosition() @@ -483,12 +497,12 @@ dc.DrawText(text, x + tw, y) dc.SetUserScale(scalex, scaley) -""" -Class that implements a Viewer based on a wx.ScrolledWindow for drawing and -manipulating graphic elements -""" class Viewer(EditorPanel, DebugViewer): + """ + Class that implements a Viewer based on a wx.ScrolledWindow for drawing and + manipulating graphic elements + """ if wx.VERSION < (2, 6, 0): def Bind(self, event, function, id = None): diff -r c02818d7e29f -r 7e61baa047f0 graphics/DebugDataConsumer.py --- a/graphics/DebugDataConsumer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/graphics/DebugDataConsumer.py Mon Aug 14 23:27:15 2017 +0300 @@ -36,6 +36,7 @@ # Date corresponding to Epoch (1970 January the first) DATE_ORIGIN = datetime.datetime(1970, 1, 1) + def get_microseconds(value): """ Function converting time duration expressed in day, second and microseconds @@ -48,6 +49,7 @@ value.microseconds) return + def generate_time(value): """ Function converting time duration expressed in day, second and microseconds @@ -90,6 +92,7 @@ return data + def generate_date(value): """ Function converting time duration expressed in day, second and microseconds @@ -99,6 +102,7 @@ """ return (DATE_ORIGIN + value).strftime("DATE#%Y-%m-%d") + def generate_datetime(value): """ Function converting time duration expressed in day, second and microseconds @@ -108,6 +112,7 @@ """ return (DATE_ORIGIN + value).strftime("DT#%Y-%m-%d-%H:%M:%S.%f") + def generate_timeofday(value): """ Function converting time duration expressed in day, second and microseconds @@ -147,13 +152,13 @@ # Debug Data Consumer Class #------------------------------------------------------------------------------- -""" -Class that implements an element that consumes debug values -Value update can be inhibited during the time the associated Debug Viewer is -refreshing -""" class DebugDataConsumer: + """ + Class that implements an element that consumes debug values + Value update can be inhibited during the time the associated Debug Viewer is + refreshing + """ def __init__(self): """ diff -r c02818d7e29f -r 7e61baa047f0 graphics/FBD_Objects.py --- a/graphics/FBD_Objects.py Mon Aug 14 22:30:41 2017 +0300 +++ b/graphics/FBD_Objects.py Mon Aug 14 23:27:15 2017 +0300 @@ -31,14 +31,15 @@ # Function Block Diagram Block #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a function block -""" def TestConnectorName(name, block_type): return name in ["OUT", "MN", "MX"] or name.startswith("IN") and (block_type, name) != ("EXPT", "IN2") + class FBD_Block(Graphic_Element): + """ + Class that implements the graphic representation of a function block + """ # Create a new block def __init__(self, parent, type, name, id = None, extension = 0, inputs = None, connectors = {}, executionControl = False, executionOrder = 0): @@ -498,11 +499,11 @@ # Function Block Diagram Variable #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a variable -""" class FBD_Variable(Graphic_Element): + """ + Class that implements the graphic representation of a variable + """ # Create a new variable def __init__(self, parent, type, name, value_type, id = None, executionOrder = 0): @@ -794,11 +795,11 @@ # Function Block Diagram Connector #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a connection -""" class FBD_Connector(Graphic_Element): + """ + Class that implements the graphic representation of a connection + """ # Create a new connection def __init__(self, parent, type, name, id = None): diff -r c02818d7e29f -r 7e61baa047f0 graphics/GraphicCommons.py --- a/graphics/GraphicCommons.py Mon Aug 14 22:30:41 2017 +0300 +++ b/graphics/GraphicCommons.py Mon Aug 14 23:27:15 2017 +0300 @@ -115,6 +115,7 @@ (2, 3) : 5 } + def round_scaling(x, n, constraint=0): fraction = float(x) / float(n) if constraint == -1: @@ -129,19 +130,28 @@ Basic vector operations for calculate wire points """ -# Create a vector from two points and define if vector must be normal + def vector(p1, p2, normal = True): + """ + Create a vector from two points and define if vector must be normal + """ vector = (p2.x - p1.x, p2.y - p1.y) if normal: return normalize(vector) return vector -# Calculate the norm of a given vector + def norm(v): + """ + Calculate the norm of a given vector + """ return sqrt(v[0] * v[0] + v[1] * v[1]) -# Normalize a given vector + def normalize(v): + """ + Normalize a given vector + """ v_norm = norm(v) # Verifie if it is not a null vector if v_norm > 0: @@ -149,24 +159,32 @@ else: return v -# Calculate the scalar product of two vectors + def is_null_vector(v): + """ + Calculate the scalar product of two vectors + """ return v == (0, 0) -# Calculate the scalar product of two vectors + def add_vectors(v1, v2): + """ + Calculate the scalar product of two vectors + """ return (v1[0] + v2[0], v1[1] + v2[1]) -# Calculate the scalar product of two vectors + def product(v1, v2): + """ + Calculate the scalar product of two vectors + """ return v1[0] * v2[0] + v1[1] * v2[1] -""" -Function that calculates the nearest point of the grid defined by scaling for the given point -""" - def GetScaledEventPosition(event, dc, scaling): + """ + Function that calculates the nearest point of the grid defined by scaling for the given point + """ pos = event.GetLogicalPosition(dc) if scaling: pos.x = round(float(pos.x) / float(scaling[0])) * scaling[0] @@ -174,11 +192,11 @@ return pos -""" -Function that choose a direction during the wire points generation -""" def DirectionChoice(v_base, v_target, dir_target): + """ + Function that choose a direction during the wire points generation + """ dir_product = product(v_base, v_target) if dir_product < 0: return (-v_base[0], -v_base[1]) @@ -186,6 +204,7 @@ return dir_target return v_base + def MiterPen(colour, width=1, style=wx.SOLID): pen = wx.Pen(colour, width, style) pen.SetJoin(wx.JOIN_MITER) @@ -196,21 +215,25 @@ # Helpers for highlighting text #------------------------------------------------------------------------------- + def AddHighlight(highlights, infos): RemoveHighlight(highlights, infos) highlights.append(infos) + def RemoveHighlight(highlights, infos): if infos in highlights: highlights.remove(infos) return True return False + def ClearHighlight(highlights, highlight_type=None): if highlight_type is not None: return [highlight for highlight in highlights if highlight[2] != highlight_type] return [] + def DrawHighlightedText(dc, text, highlights, x, y): current_pen = dc.GetPen() dc.SetPen(wx.TRANSPARENT_PEN) @@ -229,11 +252,11 @@ # Graphic element base class #------------------------------------------------------------------------------- -""" -Class that implements a generic graphic element -""" class Graphic_Element(ToolTipProducer): + """ + Class that implements a generic graphic element + """ # Create a new graphic element def __init__(self, parent, id = None): @@ -684,11 +707,11 @@ # Group of graphic elements #------------------------------------------------------------------------------- -""" -Class that implements a group of graphic elements -""" class Graphic_Group(Graphic_Element): + """ + Class that implements a group of graphic elements + """ # Create a new group of graphic elements def __init__(self, parent): @@ -1002,11 +1025,11 @@ # Connector for all types of blocks #------------------------------------------------------------------------------- -""" -Class that implements a connector for any type of block -""" class Connector(DebugDataConsumer, ToolTipProducer): + """ + Class that implements a connector for any type of block + """ # Create a new connector def __init__(self, parent, name, type, position, direction, negated = False, edge = "none", onlyone = False): @@ -1536,11 +1559,11 @@ # Common Wire Element #------------------------------------------------------------------------------- -""" -Class that implements a wire for connecting two blocks -""" class Wire(Graphic_Element, DebugDataConsumer): + """ + Class that implements a wire for connecting two blocks + """ # Create a new wire def __init__(self, parent, start = None, end = None): @@ -2716,6 +2739,7 @@ # Graphic comment element #------------------------------------------------------------------------------- + def FilterHighlightsByRow(highlights, row, length): _highlights = [] for start, end, highlight_type in highlights: @@ -2727,6 +2751,7 @@ _highlights.append((start, end, highlight_type)) return _highlights + def FilterHighlightsByColumn(highlights, start_col, end_col): _highlights = [] for start, end, highlight_type in highlights: @@ -2736,11 +2761,11 @@ _highlights.append((start, end, highlight_type)) return _highlights -""" -Class that implements a comment -""" class Comment(Graphic_Element): + """ + Class that implements a comment + """ # Create a new comment def __init__(self, parent, content, id = None): diff -r c02818d7e29f -r 7e61baa047f0 graphics/LD_Objects.py --- a/graphics/LD_Objects.py Mon Aug 14 22:30:41 2017 +0300 +++ b/graphics/LD_Objects.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,11 +32,11 @@ # Ladder Diagram PowerRail #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a power rail -""" class LD_PowerRail(Graphic_Element): + """ + Class that implements the graphic representation of a power rail + """ # Create a new power rail def __init__(self, parent, type, id=None, connectors=1): @@ -343,11 +343,11 @@ # Ladder Diagram Contact #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a contact -""" class LD_Contact(Graphic_Element, DebugDataConsumer): + """ + Class that implements the graphic representation of a contact + """ # Create a new contact def __init__(self, parent, type, name, id = None): @@ -689,11 +689,11 @@ # Ladder Diagram Coil #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a coil -""" class LD_Coil(Graphic_Element): + """ + Class that implements the graphic representation of a coil + """ # Create a new coil def __init__(self, parent, type, name, id = None): diff -r c02818d7e29f -r 7e61baa047f0 graphics/RubberBand.py --- a/graphics/RubberBand.py Mon Aug 14 22:30:41 2017 +0300 +++ b/graphics/RubberBand.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,11 +30,11 @@ # Viewer RubberBand #------------------------------------------------------------------------------- -""" -Class that implements a rubberband for graphic Viewers -""" class RubberBand: + """ + Class that implements a rubberband for graphic Viewers + """ def __init__(self, viewer): """ diff -r c02818d7e29f -r 7e61baa047f0 graphics/SFC_Objects.py --- a/graphics/SFC_Objects.py Mon Aug 14 22:30:41 2017 +0300 +++ b/graphics/SFC_Objects.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ from graphics.DebugDataConsumer import DebugDataConsumer from plcopen.structures import * + def GetWireSize(block): if isinstance(block, SFC_Step): return SFC_WIRE_MIN_SIZE + block.GetActionExtraLineNumber() * SFC_ACTION_MIN_SIZE[1] @@ -38,11 +39,11 @@ # Sequencial Function Chart Step #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a step -""" class SFC_Step(Graphic_Element, DebugDataConsumer): + """ + Class that implements the graphic representation of a step + """ # Create a new step def __init__(self, parent, name, initial = False, id = None): @@ -571,11 +572,11 @@ # Sequencial Function Chart Transition #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a transition -""" class SFC_Transition(Graphic_Element, DebugDataConsumer): + """ + Class that implements the graphic representation of a transition + """ # Create a new transition def __init__(self, parent, type = "reference", condition = None, priority = 0, id = None): @@ -1040,12 +1041,12 @@ # Sequencial Function Chart Divergence and Convergence #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a divergence or convergence, -selection or simultaneous -""" class SFC_Divergence(Graphic_Element): + """ + Class that implements the graphic representation of a divergence or convergence, + selection or simultaneous + """ # Create a new divergence def __init__(self, parent, type, number = 2, id = None): @@ -1502,11 +1503,10 @@ # Sequencial Function Chart Jump to Step #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of a jump to step -""" - class SFC_Jump(Graphic_Element): + """ + Class that implements the graphic representation of a jump to step + """ # Create a new jump def __init__(self, parent, target, id = None): @@ -1778,11 +1778,11 @@ # Sequencial Function Chart Action Block #------------------------------------------------------------------------------- -""" -Class that implements the graphic representation of an action block -""" class SFC_ActionBlock(Graphic_Element): + """ + Class that implements the graphic representation of an action block + """ # Create a new action block def __init__(self, parent, actions = [], id = None): diff -r c02818d7e29f -r 7e61baa047f0 graphics/ToolTipProducer.py --- a/graphics/ToolTipProducer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/graphics/ToolTipProducer.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,11 +30,11 @@ # Tool Tip Producer class #------------------------------------------------------------------------------- -""" -Class that implements an element that generate Tool Tip -""" class ToolTipProducer: + """ + Class that implements an element that generate Tool Tip + """ def __init__(self, parent): """ diff -r c02818d7e29f -r 7e61baa047f0 i18n/mki18n.py --- a/i18n/mki18n.py Mon Aug 14 22:30:41 2017 +0300 +++ b/i18n/mki18n.py Mon Aug 14 23:27:15 2017 +0300 @@ -93,6 +93,7 @@ # ----------------------------------------------------------------------------- + def getlanguageDict(): languageDict = {} @@ -210,10 +211,7 @@ os.system(cmd) os.chdir(currentDir) -# ----------------------------------------------------------------------------- -# c a t P O ( ) -- Concatenate one or several PO files with the application domain files. -- -# ^^^^^^^^^^^^^ -# + def catPO(applicationDirectoryPath, listOf_extraPo, applicationDomain=None, targetDir=None, verbose=0) : """Concatenate one or several PO files with the application domain files. """ @@ -248,10 +246,7 @@ os.system(cmd) os.chdir(currentDir) -# ----------------------------------------------------------------------------- -# m a k e M O ( ) -- Compile the Portable Object files into the Machine Object stored in the right location. -- -# ^^^^^^^^^^^^^^^ -# + def makeMO(applicationDirectoryPath,targetDir='./locale',applicationDomain=None, verbose=0, forceEnglish=0) : """Compile the Portable Object files into the Machine Object stored in the right location. @@ -297,10 +292,7 @@ os.system(cmd) os.chdir(currentDir) -# ----------------------------------------------------------------------------- -# p r i n t U s a g e -- Displays how to use this script from the command line -- -# ^^^^^^^^^^^^^^^^^^^ -# + def printUsage(errorMsg=None) : """Displays how to use this script from the command line.""" print """ @@ -337,10 +329,7 @@ if errorMsg: print "\n ERROR: %s" % errorMsg -# ----------------------------------------------------------------------------- -# f i l e B a s e O f ( ) -- Return base name of filename -- -# ^^^^^^^^^^^^^^^^^^^^^^^ -# + def fileBaseOf(filename,withPath=0) : """fileBaseOf(filename,withPath) ---> string @@ -378,10 +367,8 @@ return filename else: return os.path.basename(filename) -# ----------------------------------------------------------------------------- -# m k d i r ( ) -- Create a directory (and possibly the entire tree) -- -# ^^^^^^^^^^^^^ -# + + def mkdir(directory) : """Create a directory (and possibly the entire tree). @@ -420,10 +407,7 @@ os.mkdir(theDir) theDir += '/' -# ----------------------------------------------------------------------------- -# u n i x p a t h ( ) -- Return a path name that contains Unix separator. -- -# ^^^^^^^^^^^^^^^^^^^ -# + def unixpath(thePath) : r"""Return a path name that contains Unix separator. diff -r c02818d7e29f -r 7e61baa047f0 plcopen/definitions.py --- a/plcopen/definitions.py Mon Aug 14 22:30:41 2017 +0300 +++ b/plcopen/definitions.py Mon Aug 14 23:27:15 2017 +0300 @@ -50,6 +50,7 @@ StdFuncsCSV = join(sd,"iec_std.csv") + def GetBlockInfos(pou): infos = pou.getblockInfos() infos["inputs"] = [ diff -r c02818d7e29f -r 7e61baa047f0 plcopen/plcopen.py --- a/plcopen/plcopen.py Mon Aug 14 22:30:41 2017 +0300 +++ b/plcopen/plcopen.py Mon Aug 14 23:27:15 2017 +0300 @@ -59,6 +59,7 @@ FILTER_ADDRESS_MODEL = "(%%[IQM](?:[XBWDL])?)(%s)((?:\.[0-9]+)*)" + def update_address(address, address_model, new_leading): result = address_model.match(address) if result is None: @@ -66,6 +67,7 @@ groups = result.groups() return groups[0] + new_leading + groups[2] + def _init_and_compare(function, v1, v2): if v1 is None: return v2 @@ -73,10 +75,11 @@ return function(v1, v2) return v1 -""" -Helper class for bounding_box calculation -""" + class rect: + """ + Helper class for bounding_box calculation + """ def __init__(self, x=None, y=None, width=None, height=None): self.x_min = x @@ -108,12 +111,14 @@ height = self.y_max - self.y_min return self.x_min, self.y_min, width, height + def TextLenInRowColumn(text): if text == "": return (0, 0) lines = text.split("\n") return len(lines) - 1, len(lines[-1]) + def CompilePattern(criteria): flag = 0 if criteria["case_sensitive"] else re.IGNORECASE find_pattern = criteria["find_pattern"] @@ -121,6 +126,7 @@ find_pattern = re.escape(find_pattern) criteria["pattern"] = re.compile(find_pattern, flag) + def TestTextElement(text, criteria): lines = text.splitlines() test_result = [] @@ -135,6 +141,7 @@ break return test_result + def TextMatched(str1, str2): return str1 and str2 and (str1.upper() == str2.upper()) @@ -165,6 +172,7 @@ """ + def LOAD_POU_INSTANCES_PROJECT_TEMPLATE(body_type): return LOAD_POU_PROJECT_TEMPLATE % """ @@ -189,6 +197,7 @@ ActionBlocksXPath = PLCOpen_XPath("ppx:types/ppx:pous/ppx:pou/ppx:body/*/ppx:actionBlock") ActionBlocksConnectionPointOutXPath = PLCOpen_XPath("ppx:connectionPointOut") + def LoadProjectXML(project_xml): project_xml = project_xml.replace( "http://www.plcopen.org/xml/tc6.xsd", @@ -266,6 +275,7 @@ except Exception, e: return None, e.message + def LoadProject(filepath): project_file = open(filepath) project_xml = project_file.read() @@ -273,6 +283,8 @@ return LoadProjectXML(project_xml) project_pou_xpath = PLCOpen_XPath("/ppx:project/ppx:types/ppx:pous/ppx:pou") + + def LoadPou(xml_string): root, error = LoadProjectXML(LOAD_POU_PROJECT_TEMPLATE % xml_string) return project_pou_xpath(root)[0], error @@ -281,11 +293,14 @@ body_type: PLCOpen_XPath( "/ppx:project/ppx:types/ppx:pous/ppx:pou[@name='paste_pou']/ppx:body/ppx:%s/*" % body_type) for body_type in ["FBD", "LD", "SFC"]} + + def LoadPouInstances(xml_string, body_type): root, error = LoadProjectXML( LOAD_POU_INSTANCES_PROJECT_TEMPLATE(body_type) % xml_string) return project_pou_instances_xpath[body_type](root), error + def SaveProject(project, filepath): project_file = open(filepath, 'w') project_file.write(etree.tostring( @@ -625,6 +640,7 @@ return 0, 0 setattr(cls, "getscaling", getscaling) + def _Search(attributes, criteria, parent_infos): search_result = [] for attr, value in attributes: @@ -632,6 +648,7 @@ search_result.extend([(tuple(parent_infos + [attr]),) + result for result in TestTextElement(value, criteria)]) return search_result + def _updateConfigurationResourceElementName(self, old_name, new_name): for varlist in self.getglobalVars(): for var in varlist.getvariable(): @@ -642,6 +659,7 @@ if TextMatched(var.getname(), old_name): var.setname(new_name) + def _updateConfigurationResourceElementAddress(self, address_model, new_leading): for varlist in self.getglobalVars(): for var in varlist.getvariable(): @@ -649,6 +667,7 @@ if var_address is not None: var.setaddress(update_address(var_address, address_model, new_leading)) + def _removeConfigurationResourceVariableByAddress(self, address): for varlist in self.getglobalVars(): variables = varlist.getvariable() @@ -656,6 +675,7 @@ if variables[i].getaddress() == address: variables.remove(variables[i]) + def _removeConfigurationResourceVariableByFilter(self, address_model): for varlist in self.getglobalVars(): variables = varlist.getvariable() @@ -666,6 +686,7 @@ if result is not None: variables.remove(variables[i]) + def _SearchInConfigurationResource(self, criteria, parent_infos=[]): search_result = _Search([("name", self.getname())], criteria, parent_infos) var_number = 0 @@ -936,6 +957,7 @@ return search_result setattr(cls, "Search", Search) + def _updateBaseTypeElementName(self, old_name, new_name): self.baseType.updateElementName(old_name, new_name) @@ -1006,6 +1028,7 @@ return search_result setattr(cls, "Search", Search) + def _SearchInSubrange(self, criteria, parent_infos=[]): search_result = self.baseType.Search(criteria, parent_infos) search_result.extend(_Search([("lower", self.range.getlower()), @@ -1039,6 +1062,7 @@ return search_result setattr(cls, "Search", Search) + def _getvariableTypeinfos(variable_type): type_content = variable_type.getcontent() type_content_type = type_content.getLocalTag() @@ -1450,48 +1474,62 @@ return search_result setattr(cls, "Search", Search) + def setbodyType(self, body_type): if body_type in ["IL", "ST", "LD", "FBD", "SFC"]: self.body.setcontent(PLCOpenParser.CreateElement(body_type, "body")) else: raise ValueError, "%s isn't a valid body type!" % type + def getbodyType(self): return self.body.getcontent().getLocalTag() + def resetexecutionOrder(self): self.body.resetexecutionOrder() + def compileexecutionOrder(self): self.body.compileexecutionOrder() + def setelementExecutionOrder(self, instance, new_executionOrder): self.body.setelementExecutionOrder(instance, new_executionOrder) + def addinstance(self, instance): self.body.appendcontentInstance(instance) + def getinstances(self): return self.body.getcontentInstances() + def getinstance(self, id): return self.body.getcontentInstance(id) + def getrandomInstance(self, exclude): return self.body.getcontentRandomInstance(exclude) + def getinstanceByName(self, name): return self.body.getcontentInstanceByName(name) + def removeinstance(self, id): self.body.removecontentInstance(id) + def settext(self, text): self.body.settext(text) + def gettext(self): return self.body.gettext() + def hasblock(self, name=None, block_type=None): if self.getbodyType() in ["FBD", "LD", "SFC"]: for instance in self.getinstances(): @@ -1502,9 +1540,11 @@ return self.body.hasblock(block_type) return False + def updateElementName(self, old_name, new_name): self.body.updateElementName(old_name, new_name) + def updateElementAddress(self, address_model, new_leading): self.body.updateElementAddress(address_model, new_leading) @@ -1746,21 +1786,27 @@ return search_result setattr(cls, "Search", Search) + def getx(self): return self.position.getx() + def gety(self): return self.position.gety() + def setx(self, x): self.position.setx(x) + def sety(self, y): self.position.sety(y) + def _getBoundingBox(self): return rect(self.getx(), self.gety(), self.getwidth(), self.getheight()) + def _getConnectionsBoundingBox(connectionPointIn): bbox = rect() connections = connectionPointIn.getconnections() @@ -1770,18 +1816,21 @@ bbox.update(x, y) return bbox + def _getBoundingBoxSingle(self): bbox = _getBoundingBox(self) if self.connectionPointIn is not None: bbox.union(_getConnectionsBoundingBox(self.connectionPointIn)) return bbox + def _getBoundingBoxMultiple(self): bbox = _getBoundingBox(self) for connectionPointIn in self.getconnectionPointIn(): bbox.union(_getConnectionsBoundingBox(connectionPointIn)) return bbox + def _filterConnections(connectionPointIn, localId, connections): in_connections = connectionPointIn.getconnections() if in_connections is not None: @@ -1791,18 +1840,22 @@ not connections.has_key((connected, localId)): connectionPointIn.remove(connection) + def _filterConnectionsSingle(self, connections): if self.connectionPointIn is not None: _filterConnections(self.connectionPointIn, self.localId, connections) + def _filterConnectionsMultiple(self, connections): for connectionPointIn in self.getconnectionPointIn(): _filterConnections(connectionPointIn, self.localId, connections) + def _getconnectionsdefinition(instance, connections_end): local_id = instance.getlocalId() return dict([((local_id, end), True) for end in connections_end]) + def _updateConnectionsId(connectionPointIn, translation): connections_end = [] connections = connectionPointIn.getconnections() @@ -1814,22 +1867,26 @@ connections_end.append(new_reflocalId) return connections_end + def _updateConnectionsIdSingle(self, translation): connections_end = [] if self.connectionPointIn is not None: connections_end = _updateConnectionsId(self.connectionPointIn, translation) return _getconnectionsdefinition(self, connections_end) + def _updateConnectionsIdMultiple(self, translation): connections_end = [] for connectionPointIn in self.getconnectionPointIn(): connections_end.extend(_updateConnectionsId(connectionPointIn, translation)) return _getconnectionsdefinition(self, connections_end) + def _translate(self, dx, dy): self.setx(self.getx() + dx) self.sety(self.gety() + dy) + def _translateConnections(connectionPointIn, dx, dy): connections = connectionPointIn.getconnections() if connections is not None: @@ -1838,22 +1895,27 @@ position.setx(position.getx() + dx) position.sety(position.gety() + dy) + def _translateSingle(self, dx, dy): _translate(self, dx, dy) if self.connectionPointIn is not None: _translateConnections(self.connectionPointIn, dx, dy) + def _translateMultiple(self, dx, dy): _translate(self, dx, dy) for connectionPointIn in self.getconnectionPointIn(): _translateConnections(connectionPointIn, dx, dy) + def _updateElementName(self, old_name, new_name): pass + def _updateElementAddress(self, address_model, new_leading): pass + def _SearchInElement(self, criteria, parent_infos=[]): return [] @@ -1872,6 +1934,7 @@ "multiple": _updateConnectionsIdMultiple}, } + def _initElementClass(name, parent, connectionPointInType="none"): cls = PLCOpenParser.GetElementClass(name, parent) if cls: @@ -1959,13 +2022,16 @@ _initElementClass("leftPowerRail", "ldObjects") _initElementClass("rightPowerRail", "ldObjects", "multiple") + def _UpdateLDElementName(self, old_name, new_name): if TextMatched(self.variable, old_name): self.variable = new_name + def _UpdateLDElementAddress(self, address_model, new_leading): self.variable = update_address(self.variable, address_model, new_leading) + def _getSearchInLDElement(ld_element_type): def SearchInLDElement(self, criteria, parent_infos=[]): return _Search([("reference", self.variable)], criteria, parent_infos + [ld_element_type, self.getlocalId()]) @@ -2224,13 +2290,16 @@ return search_result setattr(cls, "Search", Search) + def _SearchInIOVariable(self, criteria, parent_infos=[]): return _Search([("expression", self.expression)], criteria, parent_infos + ["io_variable", self.getlocalId()]) + def _UpdateIOElementName(self, old_name, new_name): if TextMatched(self.expression, old_name): self.expression = new_name + def _UpdateIOElementAddress(self, address_model, new_leading): self.expression = update_address(self.expression, address_model, new_leading) @@ -2404,6 +2473,7 @@ return self.content.getvalue() setattr(cls, "getvalue", getvalue) + def extractValues(values): items = values.split(",") i = 1 diff -r c02818d7e29f -r 7e61baa047f0 plcopen/structures.py --- a/plcopen/structures.py Mon Aug 14 22:30:41 2017 +0300 +++ b/plcopen/structures.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,10 +30,11 @@ TypeHierarchy = dict(TypeHierarchy_list) -""" -returns true if the given data type is the same that "reference" meta-type or one of its types. -""" + def IsOfType(type, reference): + """ + Returns true if the given data type is the same that "reference" meta-type or one of its types. + """ if reference is None: return True elif type == reference: @@ -44,10 +45,11 @@ return IsOfType(parent_type, reference) return False -""" -returns list of all types that correspont to the ANY* meta type -""" + def GetSubTypes(type): + """ + Returns list of all types that correspont to the ANY* meta type + """ return [typename for typename, parenttype in TypeHierarchy.items() if not typename.startswith("ANY") and IsOfType(typename, type)] DataTypeRange = dict(DataTypeRange_list) @@ -82,36 +84,41 @@ "(?:%(letter)s|_(?:%(letter)s|%(digit)s))(?:_?(?:%(letter)s|%(digit)s))*$" % {"letter": "[a-zA-Z]", "digit": "[0-9]"}) -# Test if identifier is valid + def TestIdentifier(identifier): - return IDENTIFIER_MODEL.match(identifier) is not None + """ + Test if identifier is valid + """ + return IDENTIFIER_MODEL.match(identifier) is not None #------------------------------------------------------------------------------- # Standard functions list generation #------------------------------------------------------------------------------- -""" -take a .csv file and translate it it a "csv_table" -""" def csv_file_to_table(file): + """ + take a .csv file and translate it it a "csv_table" + """ return [ map(string.strip,line.split(';')) for line in file.xreadlines()] -""" -seek into the csv table to a section ( section_name match 1st field ) -return the matching row without first field -""" + def find_section(section_name, table): + """ + seek into the csv table to a section ( section_name match 1st field ) + return the matching row without first field + """ fields = [None] while(fields[0] != section_name): fields = table.pop(0) return fields[1:] -""" -extract the standard functions standard parameter names and types... -return a { ParameterName: Type, ...} -""" + def get_standard_funtions_input_variables(table): + """ + extract the standard functions standard parameter names and types... + return a { ParameterName: Type, ...} + """ variables = find_section("Standard_functions_variables_types", table) standard_funtions_input_variables = {} fields = [True,True] @@ -121,12 +128,13 @@ standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type'] return standard_funtions_input_variables -""" -translate .csv file input declaration into PLCOpenEditor interessting values -in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...} -return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] -""" + def csv_input_translate(str_decl, variables, base): + """ + translate .csv file input declaration into PLCOpenEditor interessting values + in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...} + return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] + """ decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',') params = [] @@ -145,8 +153,9 @@ return params -""" -Returns this kind of declaration for all standard functions +def get_standard_funtions(table): + """ + Returns this kind of declaration for all standard functions [{"name" : "Numerical", 'list': [ { 'baseinputnumber': 1, @@ -157,8 +166,7 @@ 'name': 'ADD', 'outputs': [('OUT', 'ANY_NUM', 'none')], 'type': 'function'}, ...... ] },.....] -""" -def get_standard_funtions(table): + """ variables = get_standard_funtions_input_variables(table) diff -r c02818d7e29f -r 7e61baa047f0 py_ext/PythonEditor.py --- a/py_ext/PythonEditor.py Mon Aug 14 22:30:41 2017 +0300 +++ b/py_ext/PythonEditor.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ from controls.CustomStyledTextCtrl import faces from editors.CodeFileEditor import CodeFileEditor, CodeEditor + class PythonCodeEditor(CodeEditor): KEYWORDS = keyword.kwlist diff -r c02818d7e29f -r 7e61baa047f0 py_ext/PythonFileCTNMixin.py --- a/py_ext/PythonFileCTNMixin.py Mon Aug 14 22:30:41 2017 +0300 +++ b/py_ext/PythonFileCTNMixin.py Mon Aug 14 23:27:15 2017 +0300 @@ -33,6 +33,7 @@ from CodeFileTreeNode import CodeFile from PythonEditor import PythonEditor + class PythonFileCTNMixin(CodeFile): CODEFILE_NAME = "PyFile" diff -r c02818d7e29f -r 7e61baa047f0 py_ext/py_ext.py --- a/py_ext/py_ext.py Mon Aug 14 22:30:41 2017 +0300 +++ b/py_ext/py_ext.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ from PythonFileCTNMixin import PythonFileCTNMixin import util.paths as paths + class PythonLibrary(POULibrary): def GetLibraryPath(self): return paths.AbsNeighbourFile(__file__, "pous.xml") @@ -56,6 +57,7 @@ return (["py_ext"], [(Gen_Pythonfile_path, IECCFLAGS)], True), "" + class PythonFile(PythonFileCTNMixin): def GetIconName(self): diff -r c02818d7e29f -r 7e61baa047f0 runtime/NevowServer.py --- a/runtime/NevowServer.py Mon Aug 14 22:30:41 2017 +0300 +++ b/runtime/NevowServer.py Mon Aug 14 23:27:15 2017 +0300 @@ -36,6 +36,7 @@ WorkingDir = None + class PLCHMI(athena.LiveElement): initialised = False @@ -46,16 +47,19 @@ def HMIinitialisation(self): self.HMIinitialised(None) + class DefaultPLCStartedHMI(PLCHMI): docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ tags.h1["PLC IS NOW STARTED"], ]) + class PLCStoppedHMI(PLCHMI): docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ tags.h1["PLC IS STOPPED"], ]) + class MainPage(athena.LiveElement): jsClass = u"WebInterface.PLC" docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ @@ -110,6 +114,7 @@ for child in self.liveFragmentChildren[:]: child.detach() + class WebInterface(athena.LivePage): docFactory = loaders.stan([tags.raw(xhtml_header), @@ -173,6 +178,7 @@ #print reason #print "We will be called back when the client disconnects" + def RegisterWebsite(port): website = WebInterface() site = appserver.NevowSite(website) @@ -182,6 +188,7 @@ print _("HTTP interface port :"), port return website + class statuslistener: def __init__(self, site): self.oldstate = None @@ -194,5 +201,6 @@ if action is not None: action () self.oldstate = state + def website_statuslistener_factory(site): return statuslistener(site).listen diff -r c02818d7e29f -r 7e61baa047f0 runtime/PLCObject.py --- a/runtime/PLCObject.py Mon Aug 14 22:30:41 2017 +0300 +++ b/runtime/PLCObject.py Mon Aug 14 23:27:15 2017 +0300 @@ -39,6 +39,8 @@ from _ctypes import dlopen, dlclose import traceback + + def get_last_traceback(tb): while tb.tb_next: tb = tb.tb_next @@ -49,10 +51,12 @@ "win32":".dll", }.get(sys.platform, "") + def PLCprint(message): sys.stdout.write("PLCobject : "+message+"\n") sys.stdout.flush() + class PLCObject(pyro.ObjBase): def __init__(self, workingdir, daemon, argv, statuschange, evaluator, pyruntimevars): pyro.ObjBase.__init__(self) diff -r c02818d7e29f -r 7e61baa047f0 runtime/ServicePublisher.py --- a/runtime/ServicePublisher.py Mon Aug 14 22:30:41 2017 +0300 +++ b/runtime/ServicePublisher.py Mon Aug 14 23:27:15 2017 +0300 @@ -27,6 +27,7 @@ service_type = '_PYRO._tcp.local.' + class ServicePublisher(): def __init__(self): # type: fully qualified service type name diff -r c02818d7e29f -r 7e61baa047f0 runtime/WampClient.py --- a/runtime/WampClient.py Mon Aug 14 22:30:41 2017 +0300 +++ b/runtime/WampClient.py Mon Aug 14 23:27:15 2017 +0300 @@ -51,6 +51,7 @@ DoOnJoin = [] + def GetCallee(name): """ Get Callee or Subscriber corresponding to '.' spearated object path """ global _PySrv @@ -59,6 +60,7 @@ while names: obj = getattr(obj, names.pop(0)) return obj + class WampSession(wamp.ApplicationSession): @inlineCallbacks @@ -81,6 +83,7 @@ _WampSession = None print 'WAMP session left' + class ReconnectingWampWebSocketClientFactory(WampWebSocketClientFactory, ReconnectingClientFactory): def clientConnectionFailed(self, connector, reason): print("WAMP Client connection failed .. retrying ..") @@ -89,11 +92,13 @@ print("WAMP Client connection lost .. retrying ..") self.retry(connector) + def LoadWampClientConf(wampconf): WSClientConf = json.load(open(wampconf)) return WSClientConf + def RegisterWampClient(wampconf): WSClientConf = LoadWampClientConf(wampconf) @@ -122,10 +127,12 @@ print "WAMP client connecting to :",WSClientConf["url"] return conn + def GetSession(): global _WampSession return _WampSession + def SetServer(pysrv): global _PySrv _PySrv = pysrv diff -r c02818d7e29f -r 7e61baa047f0 svgui/pyjs/build.py --- a/svgui/pyjs/build.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/pyjs/build.py Mon Aug 14 23:27:15 2017 +0300 @@ -63,6 +63,7 @@ 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) @@ -103,6 +104,7 @@ 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. @@ -523,15 +525,19 @@ 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): + """ + creates sub-dependencies e.g. pyjamas.ui.Widget + creates pyjamas.ui.Widget, pyjamas.ui and pyjamas. + """ d = [] m = m.split(".") for i in range(0, len(m)): @@ -540,6 +546,7 @@ import time + def add_subdeps(deps, mod_name): sd = subdeps(mod_name) if len(sd) == 1: @@ -558,14 +565,18 @@ #print deps return res -# makes unique and preserves list order + def uniquify(md): + """ + makes unique and preserves list order + """ 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') @@ -578,6 +589,7 @@ return uniquify(md) + def filter_deps(app_name, deps): res = {} @@ -588,11 +600,13 @@ 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: @@ -655,6 +669,7 @@ return ordered_deps + def main(): global app_platforms diff -r c02818d7e29f -r 7e61baa047f0 svgui/pyjs/jsonrpc/django/jsonrpc.py --- a/svgui/pyjs/jsonrpc/django/jsonrpc.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/pyjs/jsonrpc/django/jsonrpc.py Mon Aug 14 23:27:15 2017 +0300 @@ -18,11 +18,13 @@ # 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 : @@ -64,6 +66,7 @@ from django import forms + def builderrors(form): d = {} for error in form.errors.keys(): @@ -91,6 +94,7 @@ 'IPAddressField': ['max_length', 'min_length'], } + def describe_field_errors(field): res = {} field_type = field.__class__.__name__ @@ -102,6 +106,7 @@ res['fields'] = map(describe_field, field.fields) return res + def describe_fields_errors(fields, field_names): res = {} if not field_names: @@ -111,6 +116,7 @@ res[name] = describe_field_errors(field) return res + def describe_field(field): res = {} field_type = field.__class__.__name__ @@ -121,6 +127,7 @@ res['fields'] = map(describe_field, field.fields) return res + def describe_fields(fields, field_names): res = {} if not field_names: @@ -130,6 +137,7 @@ res[name] = describe_field(field) return res + class FormProcessor(JSONRPCService): def __init__(self, forms, _formcls=None): @@ -206,6 +214,7 @@ import datetime from datetime import date + def dict_datetimeflatten(item): d = {} for k, v in item.items(): @@ -218,6 +227,7 @@ d[k] = v return d + def json_convert(l, fields=None): res = [] for item in serialize('python', l, fields=fields): diff -r c02818d7e29f -r 7e61baa047f0 svgui/pyjs/jsonrpc/jsonrpc.py --- a/svgui/pyjs/jsonrpc/jsonrpc.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/pyjs/jsonrpc/jsonrpc.py Mon Aug 14 23:27:15 2017 +0300 @@ -2,6 +2,7 @@ import types import sys + class JSONRPCServiceBase: def __init__(self): diff -r c02818d7e29f -r 7e61baa047f0 svgui/pyjs/jsonrpc/web2py/jsonrpc.py --- a/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Mon Aug 14 23:27:15 2017 +0300 @@ -1,5 +1,6 @@ from pyjs.jsonrpc import JSONRPCServiceBase + class JSONRPCService(JSONRPCServiceBase): def serve(self): diff -r c02818d7e29f -r 7e61baa047f0 svgui/pyjs/lib/pyjslib.py --- a/svgui/pyjs/lib/pyjslib.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/pyjs/lib/pyjslib.py Mon Aug 14 23:27:15 2017 +0300 @@ -19,6 +19,7 @@ # must declare import _before_ importing sys + def import_module(path, parent_module, module_name, dynamic=1, async=False): """ """ @@ -184,11 +185,13 @@ } """) + class Object: pass object = Object + class Modload: def __init__(self, path, app_modlist, app_imported_fn, dynamic, @@ -212,11 +215,13 @@ 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): @@ -225,6 +230,7 @@ import sys + class BaseException: name = "BaseException" @@ -242,27 +248,31 @@ 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): @@ -407,6 +417,7 @@ """) + class Class: def __init__(self, name): self.name = name @@ -414,6 +425,7 @@ def __str___(self): return self.name + def eq(a,b): JS(""" if (pyjslib.hasattr(a, "__cmp__")) { @@ -424,6 +436,7 @@ return a == b; """) + def cmp(a,b): if hasattr(a, "__cmp__"): return a.__cmp__(b) @@ -436,6 +449,7 @@ 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 @@ -456,6 +470,7 @@ return Boolean(v); """) + class List: def __init__(self, data=None): JS(""" @@ -605,6 +620,7 @@ list = List + class Tuple: def __init__(self, data=None): JS(""" @@ -900,6 +916,8 @@ dict = Dict # taken from mochikit: range( [start,] stop[, step] ) + + def range(): JS(""" var start = 0; @@ -930,6 +948,7 @@ } """) + def slice(object, lower, upper): JS(""" if (pyjslib.isString(object)) { @@ -948,6 +967,7 @@ return null; """) + def str(text): JS(""" if (pyjslib.hasattr(text,"__str__")) { @@ -956,6 +976,7 @@ return String(text); """) + def ord(x): if(isString(x) and len(x) is 1): JS(""" @@ -967,11 +988,13 @@ """) return None + def chr(x): JS(""" return String.fromCharCode(x) """) + def is_basetype(x): JS(""" var t = typeof(x); @@ -983,6 +1006,7 @@ ; """) + def get_pyjs_classtype(x): JS(""" if (pyjslib.hasattr(x, "__class__")) @@ -992,6 +1016,7 @@ return null; """) + def repr(x): """ Return the string representation of 'x'. """ @@ -1088,16 +1113,19 @@ 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; @@ -1105,6 +1133,7 @@ return object.length; """) + def isinstance(object_, classinfo): if pyjslib.isUndefined(object_): return False @@ -1119,6 +1148,7 @@ else: return _isinstance(object_, classinfo) + def _isinstance(object_, classinfo): if not pyjslib.isObject(object_): return False @@ -1130,6 +1160,7 @@ return false; """) + def getattr(obj, name, default_): JS(""" if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){ @@ -1151,6 +1182,7 @@ return fnwrap; """) + def setattr(obj, name, value): JS(""" if (!pyjslib.isObject(obj)) return null; @@ -1159,6 +1191,7 @@ """) + def hasattr(obj, name): JS(""" if (!pyjslib.isObject(obj)) return false; @@ -1167,6 +1200,7 @@ return true; """) + def dir(obj): JS(""" var properties=new pyjslib.List(); @@ -1174,6 +1208,7 @@ 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 @@ -1240,6 +1275,7 @@ next_hash_id = 0 + def hash(obj): JS(""" if (obj == null) return null; @@ -1259,41 +1295,49 @@ 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 @@ -1337,6 +1381,7 @@ """) return x + def printFunc(objs): JS(""" if ($wnd.console==undefined) return; @@ -1348,6 +1393,7 @@ console.debug(s) """) + def type(clsname, bases=None, methods=None): """ creates a class, derived from bases, with methods and variables """ diff -r c02818d7e29f -r 7e61baa047f0 svgui/pyjs/lib/sys.py --- a/svgui/pyjs/lib/sys.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/pyjs/lib/sys.py Mon Aug 14 23:27:15 2017 +0300 @@ -11,22 +11,27 @@ 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))) { @@ -34,11 +39,14 @@ } sys.stacktrace.append(linedebug); """) + + def popstack(): JS(""" sys.stacktrace.pop() """) + def printstack(): JS(""" var res = ''; diff -r c02818d7e29f -r 7e61baa047f0 svgui/pyjs/pyjs.py --- a/svgui/pyjs/pyjs.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/pyjs/pyjs.py Mon Aug 14 23:27:15 2017 +0300 @@ -90,6 +90,7 @@ "tuple", ) + def pyjs_builtin_remap(name): # XXX HACK! if name == 'list': @@ -119,17 +120,20 @@ (';', 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 = {} @@ -154,9 +158,11 @@ 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 @@ -174,6 +180,7 @@ 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 """ @@ -181,6 +188,7 @@ """ % ({'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, @@ -1534,6 +1542,7 @@ import cStringIO + def translate(file_name, module_name, debug=False): f = file(file_name, "r") src = f.read() @@ -1633,10 +1642,12 @@ 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, @@ -1757,6 +1768,7 @@ usage: %s file_name [module_name] """ + def main(): import sys if len(sys.argv)<2: diff -r c02818d7e29f -r 7e61baa047f0 svgui/svgui.py --- a/svgui/svgui.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/svgui.py Mon Aug 14 23:27:15 2017 +0300 @@ -35,10 +35,12 @@ from docutil import open_svg from py_ext import PythonFileCTNMixin + class SVGUILibrary(POULibrary): def GetLibraryPath(self): return paths.AbsNeighbourFile(__file__, "pous.xml") + class SVGUI(PythonFileCTNMixin): ConfNodeMethods = [ diff -r c02818d7e29f -r 7e61baa047f0 svgui/svgui_server.py --- a/svgui/svgui_server.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/svgui_server.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,11 +32,14 @@ svguiWidgets = {} currentId = 0 + + def getNewId(): global currentId currentId += 1 return currentId + class SvguiWidget: def __init__(self, classname, id, **kwargs): @@ -83,6 +86,7 @@ if self.changed: self.RefreshInterface() + def get_object_init_state(obj): # Convert objects to a dictionary of their representation attrs = obj.attrs.copy() @@ -93,6 +97,7 @@ } return d + def get_object_current_state(obj): # Convert objects to a dictionary of their representation d = { '__class__': obj.classname, @@ -101,6 +106,7 @@ } return d + class SVGUI_HMI(website.PLCHMI): jsClass = u"LiveSVGPage.LiveSVGWidget" @@ -123,6 +129,7 @@ def setattr(self, id, attrname, value): svguiWidgets[id].setinput(attrname, value) + def createSVGUIControl(*args, **kwargs): id = getNewId() gad = SvguiWidget(args[0], id, **kwargs) @@ -133,16 +140,19 @@ 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: diff -r c02818d7e29f -r 7e61baa047f0 svgui/svguilib.py --- a/svgui/svguilib.py Mon Aug 14 22:30:41 2017 +0300 +++ b/svgui/svguilib.py Mon Aug 14 23:27:15 2017 +0300 @@ -22,6 +22,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + class button: def __init__(self, parent, id, args): @@ -115,6 +116,7 @@ self.updateElements() self.dragging = False + class textControl: def __init__(self, parent, id, args): diff -r c02818d7e29f -r 7e61baa047f0 targets/Generic/__init__.py --- a/targets/Generic/__init__.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/Generic/__init__.py Mon Aug 14 23:27:15 2017 +0300 @@ -24,5 +24,6 @@ from ..toolchain_makefile import toolchain_makefile + class Generic_target(toolchain_makefile): pass diff -r c02818d7e29f -r 7e61baa047f0 targets/Linux/__init__.py --- a/targets/Linux/__init__.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/Linux/__init__.py Mon Aug 14 23:27:15 2017 +0300 @@ -24,6 +24,7 @@ from ..toolchain_gcc import toolchain_gcc + class Linux_target(toolchain_gcc): dlopen_prefix = "./" extension = ".so" diff -r c02818d7e29f -r 7e61baa047f0 targets/Win32/__init__.py --- a/targets/Win32/__init__.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/Win32/__init__.py Mon Aug 14 23:27:15 2017 +0300 @@ -24,6 +24,7 @@ from ..toolchain_gcc import toolchain_gcc + class Win32_target(toolchain_gcc): dlopen_prefix = "" extension = ".dll" diff -r c02818d7e29f -r 7e61baa047f0 targets/Xenomai/__init__.py --- a/targets/Xenomai/__init__.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/Xenomai/__init__.py Mon Aug 14 23:27:15 2017 +0300 @@ -24,6 +24,7 @@ from ..toolchain_gcc import toolchain_gcc + class Xenomai_target(toolchain_gcc): dlopen_prefix = "./" extension = ".so" diff -r c02818d7e29f -r 7e61baa047f0 targets/__init__.py --- a/targets/__init__.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/__init__.py Mon Aug 14 23:27:15 2017 +0300 @@ -38,6 +38,8 @@ import util.paths as paths _base_path = paths.AbsDir(__file__) + + def _GetLocalTargetClassFactory(name): return lambda:getattr(__import__(name,globals(),locals()), name+"_target") @@ -54,9 +56,11 @@ toolchains = {"gcc": path.join(_base_path, "XSD_toolchain_gcc"), "makefile": path.join(_base_path, "XSD_toolchain_makefile")} + def GetBuilder(targetname): return targets[targetname]["class"]() + def GetTargetChoices(): DictXSD_toolchain = {} targetchoices = "" @@ -74,15 +78,18 @@ return targetchoices + def GetTargetCode(targetname): codedesc = targets[targetname]["code"] code = "\n".join([open(fpath).read() for fname, fpath in sorted(codedesc.items())]) return code + def GetHeader(): filename = paths.AbsNeighbourFile(__file__,"beremiz.h") return open(filename).read() + def GetCode(name): filename = paths.AbsNeighbourFile(__file__,name) return open(filename).read() diff -r c02818d7e29f -r 7e61baa047f0 targets/toolchain_gcc.py --- a/targets/toolchain_gcc.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/toolchain_gcc.py Mon Aug 14 23:27:15 2017 +0300 @@ -31,6 +31,7 @@ includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') + class toolchain_gcc(): """ This abstract class contains GCC specific code. diff -r c02818d7e29f -r 7e61baa047f0 targets/toolchain_makefile.py --- a/targets/toolchain_makefile.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/toolchain_makefile.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,6 +32,7 @@ includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') + class toolchain_makefile(): def __init__(self, CTRInstance): self.CTRInstance = CTRInstance diff -r c02818d7e29f -r 7e61baa047f0 targets/typemapping.py --- a/targets/typemapping.py Mon Aug 14 22:30:41 2017 +0300 +++ b/targets/typemapping.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,6 +30,7 @@ from ctypes import * from datetime import timedelta as td + class IEC_STRING(Structure): """ Must be changed according to changes in iec_types.h @@ -37,6 +38,7 @@ _fields_ = [("len", c_uint8), ("body", c_char * 126)] + class IEC_TIME(Structure): """ Must be changed according to changes in iec_types.h @@ -44,7 +46,10 @@ _fields_ = [("s", c_long), #tv_sec ("ns", c_long)] #tv_nsec + def _t(t, u=lambda x:x.value, p=lambda t,x:t(x)): return (t, u, p) + + def _ttime(): return (IEC_TIME, lambda x:td(0, x.s, x.ns/1000), lambda t,x:t(x.days * 24 * 3600 + x.seconds, x.microseconds*1000)) @@ -86,6 +91,7 @@ # Construct debugger natively supported types DebugTypesSize = dict([(key,sizeof(t)) for key,(t,p,u) in SameEndianessTypeTranslator.iteritems() if t is not None]) + def UnpackDebugBuffer(buff, indexes): res = [] buffoffset = 0 diff -r c02818d7e29f -r 7e61baa047f0 util/BitmapLibrary.py --- a/util/BitmapLibrary.py Mon Aug 14 22:30:41 2017 +0300 +++ b/util/BitmapLibrary.py Mon Aug 14 23:27:15 2017 +0300 @@ -37,10 +37,12 @@ # Library Helpers #------------------------------------------------------------------------------- + def AddBitmapFolder(path): if os.path.exists(path) and os.path.isdir(path) and path not in BitmapFolders: BitmapFolders.append(path) + def SearchBitmap(bmp_name): for folder in BitmapFolders: bmp_path = os.path.join(folder, bmp_name + ".png") @@ -48,6 +50,7 @@ return wx.Bitmap(bmp_path) return None + def GetBitmap(bmp_name1, bmp_name2=None, size=None): bmp = BitmapLibrary.get((bmp_name1, bmp_name2, size)) if bmp is not None: diff -r c02818d7e29f -r 7e61baa047f0 util/MiniTextControler.py --- a/util/MiniTextControler.py Mon Aug 14 22:30:41 2017 +0300 +++ b/util/MiniTextControler.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ import os + class MiniTextControler: def __init__(self, filepath, controller): diff -r c02818d7e29f -r 7e61baa047f0 util/ProcessLogger.py --- a/util/ProcessLogger.py Mon Aug 14 22:30:41 2017 +0300 +++ b/util/ProcessLogger.py Mon Aug 14 23:27:15 2017 +0300 @@ -69,6 +69,7 @@ self.finished = True self.endcallback(self.Proc.pid, err) + class ProcessLogger: def __init__(self, logger, Command, finish_callback = None, no_stdout = False, no_stderr = False, no_gui = True, diff -r c02818d7e29f -r 7e61baa047f0 util/TranslationCatalogs.py --- a/util/TranslationCatalogs.py Mon Aug 14 22:30:41 2017 +0300 +++ b/util/TranslationCatalogs.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,6 +32,7 @@ # Define locale for wx locale = wx.Locale(langid) + def GetDomain(path): for name in os.listdir(path): filepath = os.path.join(path, name) @@ -44,6 +45,7 @@ return basename return None + def AddCatalog(locale_dir): if os.path.exists(locale_dir) and os.path.isdir(locale_dir): domain = GetDomain(locale_dir) diff -r c02818d7e29f -r 7e61baa047f0 util/Zeroconf.py --- a/util/Zeroconf.py Mon Aug 14 22:30:41 2017 +0300 +++ b/util/Zeroconf.py Mon Aug 14 23:27:15 2017 +0300 @@ -183,29 +183,36 @@ # utility functions + def currentTimeMillis(): """Current system time in milliseconds""" return time.time() * 1000 # Exceptions + class NonLocalNameException(Exception): pass + class NonUniqueNameException(Exception): pass + class NamePartTooLongException(Exception): pass + class AbstractMethodException(Exception): pass + class BadTypeInNameException(Exception): pass # implementation classes + class DNSEntry(object): """A DNS entry""" @@ -254,6 +261,7 @@ result += "]" return result + class DNSQuestion(DNSEntry): """A DNS question entry""" @@ -332,6 +340,7 @@ arg = "%s/%s,%s" % (self.ttl, self.getRemainingTTL(currentTimeMillis()), other) return DNSEntry.toString(self, "record", arg) + class DNSAddress(DNSRecord): """A DNS address record""" @@ -356,6 +365,7 @@ except: return self.address + class DNSHinfo(DNSRecord): """A DNS host information record""" @@ -379,6 +389,7 @@ """String representation""" return self.cpu + " " + self.os + class DNSPointer(DNSRecord): """A DNS pointer record""" @@ -400,6 +411,7 @@ """String representation""" return self.toString(self.alias) + class DNSText(DNSRecord): """A DNS text record""" @@ -424,6 +436,7 @@ else: return self.toString(self.text) + class DNSService(DNSRecord): """A DNS service record""" @@ -451,6 +464,7 @@ """String representation""" return self.toString("%s:%s" % (self.server, self.port)) + class DNSIncoming(object): """Object representation of an incoming DNS packet""" @@ -890,6 +904,7 @@ self.condition.notify() self.condition.release() + class Listener(object): """A Listener is used by this module to listen on the multicast group to which DNS messages are sent, allowing the implementation diff -r c02818d7e29f -r 7e61baa047f0 util/misc.py --- a/util/misc.py Mon Aug 14 22:30:41 2017 +0300 +++ b/util/misc.py Mon Aug 14 23:27:15 2017 +0300 @@ -29,8 +29,9 @@ import os import sys -# helper func to check path write permission + def CheckPathPerm(path): + """ Helper func to check path write permission """ if path is None or not os.path.isdir(path): return False for root, dirs, files in os.walk(path): @@ -41,6 +42,7 @@ return False return True + def GetClassImporter(classpath): if type(classpath)==str: def fac(): @@ -50,6 +52,7 @@ else: return classpath + def InstallLocalRessources(CWD): from BitmapLibrary import AddBitmapFolder from TranslationCatalogs import AddCatalog diff -r c02818d7e29f -r 7e61baa047f0 util/paths.py --- a/util/paths.py Mon Aug 14 22:30:41 2017 +0300 +++ b/util/paths.py Mon Aug 14 23:27:15 2017 +0300 @@ -25,15 +25,18 @@ import os import sys + def AbsFile(file): if isinstance(file, str): file = unicode(file,sys.getfilesystemencoding()) return file + def AbsDir(file): file = AbsFile(file) return os.path.dirname(os.path.realpath(file)) + def AbsNeighbourFile(file, *args): return os.path.join(AbsDir(file), *args) diff -r c02818d7e29f -r 7e61baa047f0 version.py --- a/version.py Mon Aug 14 22:30:41 2017 +0300 +++ b/version.py Mon Aug 14 23:27:15 2017 +0300 @@ -28,6 +28,7 @@ import util.paths as paths + def GetCommunityHelpMsg(): return _("The best place to ask questions about Beremiz/PLCOpenEditor\n" "is project's mailing list: beremiz-devel@lists.sourceforge.net\n" @@ -38,6 +39,7 @@ "You can subscribe to the list here:\n" "https://lists.sourceforge.net/lists/listinfo/beremiz-devel") + def GetAppRevision(): rev = None app_dir=paths.AbsDir(__file__) @@ -63,6 +65,7 @@ pass return rev + def GetAboutDialogInfo(): import wx info = wx.AboutDialogInfo() diff -r c02818d7e29f -r 7e61baa047f0 wxglade_hmi/wxglade_hmi.py --- a/wxglade_hmi/wxglade_hmi.py Mon Aug 14 22:30:41 2017 +0300 +++ b/wxglade_hmi/wxglade_hmi.py Mon Aug 14 23:27:15 2017 +0300 @@ -32,6 +32,7 @@ import util.paths as paths from py_ext import PythonFileCTNMixin + class WxGladeHMI(PythonFileCTNMixin): ConfNodeMethods = [ diff -r c02818d7e29f -r 7e61baa047f0 xmlclass/xmlclass.py --- a/xmlclass/xmlclass.py Mon Aug 14 22:30:41 2017 +0300 +++ b/xmlclass/xmlclass.py Mon Aug 14 23:27:15 2017 +0300 @@ -33,6 +33,7 @@ from new import classobj from collections import OrderedDict + def CreateNode(name): node = minidom.Node() node.nodeName = name @@ -40,9 +41,11 @@ node.childNodes = [] return node + def NodeRenameAttr(node, old_name, new_name): node._attrs[new_name] = node._attrs.pop(old_name) + def NodeSetAttr(node, name, value): attr = minidom.Attr(name) text = minidom.Text() @@ -73,6 +76,7 @@ date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$') datetime_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$') + class xml_timezone(datetime.tzinfo): def SetOffset(self, offset): @@ -98,6 +102,7 @@ ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT, ] = range(13) + def NotSupportedYet(type): """ Function that generates a function that point out to user that datatype @@ -110,10 +115,11 @@ type) return GetUnknownValue -""" -This function calculates the number of whitespace for indentation -""" + def getIndent(indent, balise): + """ + This function calculates the number of whitespace for indentation + """ first = indent * 2 second = first + len(balise) + 1 return u'\t'.expandtabs(first), u'\t'.expandtabs(second) @@ -535,6 +541,7 @@ return values return GetModelNameList + def GenerateAnyInfos(infos): def GetTextElement(tree): @@ -565,6 +572,7 @@ "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase)) } + def GenerateTagInfos(infos): def ExtractTag(tree): if len(tree._attrs) > 0: @@ -591,12 +599,14 @@ "check": lambda x: x == None or infos["minOccurs"] == 0 and value == True } + def FindTypeInfos(factory, infos): if isinstance(infos, (UnicodeType, StringType)): namespace, name = DecomposeQualifiedName(infos) return factory.GetQualifiedNameInfos(name, namespace) return infos + def GetElementInitialValue(factory, infos): infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) if infos["minOccurs"] == 1: @@ -617,6 +627,7 @@ else: return [] + def GetContentInfos(name, choices): for choice_infos in choices: if choices_infos["type"] == "sequence": @@ -630,6 +641,7 @@ return choices_infos return None + def ComputeContentChoices(factory, name, infos): choices = [] for choice in infos["choices"]: @@ -650,6 +662,7 @@ choices.append((choice["name"], choice)) return choices + def GenerateContentInfos(factory, name, choices): choices_dict = {} for choice_name, infos in choices: @@ -700,6 +713,7 @@ return None, parts[0] return parts + def GenerateElement(element_name, attributes, elements_model, accept_text=False): def ExtractElement(factory, node): @@ -735,10 +749,10 @@ return ExtractElement -""" -Class that generate class from an XML Tree -""" class ClassFactory: + """ + Class that generate class from an XML Tree + """ def __init__(self, document, filepath=None, debug=False): self.Document = document @@ -1191,11 +1205,12 @@ for classname in classnames: print classname -""" -Method that generate the method for generating the xml tree structure model by -following the attributes list defined -""" + def ComputeMultiplicity(name, infos): + """ + Method that generate the method for generating the xml tree structure model by + following the attributes list defined + """ if infos["minOccurs"] == 0: if infos["maxOccurs"] == "unbounded": return "(?:%s)*" % name @@ -1217,6 +1232,7 @@ return "(?:%s){%d,%d}" % (name, infos["minOccurs"], infos["maxOccurs"]) + def GetStructurePattern(classinfos): base_structure_pattern = ( classinfos["base"].StructurePattern.pattern[:-1] @@ -1245,14 +1261,16 @@ else: raise ValueError("XSD structure not yet supported!") -""" -Method that generate the method for creating a class instance -""" + def generateClassCreateFunction(class_definition): + """ + Method that generate the method for creating a class instance + """ def classCreatefunction(): return class_definition() return classCreatefunction + def generateGetattrMethod(factory, class_definition, classinfos): attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"]) @@ -1307,6 +1325,7 @@ return getattrMethod + def generateSetattrMethod(factory, class_definition, classinfos): attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"]) @@ -1375,6 +1394,7 @@ return setattrMethod + def gettypeinfos(name, facets): if facets.has_key("enumeration") and facets["enumeration"][0] is not None: return facets["enumeration"][0] @@ -1392,6 +1412,7 @@ return limits return name + def generateGetElementAttributes(factory, classinfos): def getElementAttributes(self): attr_list = [] @@ -1406,6 +1427,7 @@ return attr_list return getElementAttributes + def generateGetElementInfos(factory, classinfos): attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) elements = dict([(element["name"], element) for element in classinfos["elements"]]) @@ -1476,6 +1498,7 @@ return {"name": name, "type": attr_type, "value": value, "use": use, "children": children} return getElementInfos + def generateSetElementValue(factory, classinfos): attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) elements = dict([(element["name"], element) for element in classinfos["elements"]]) @@ -1532,10 +1555,12 @@ self.setcontentbytype(value) return setElementValue -""" -Methods that generates the different methods for setting and getting the attributes -""" + def generateInitMethod(factory, classinfos): + """ + Methods that generates the different methods for setting and getting the attributes + """ + def initMethod(self): if classinfos.has_key("base"): classinfos["base"]._init_(self) @@ -1554,16 +1579,19 @@ map(self.append, initial) return initMethod + def generateSetMethod(attr): def setMethod(self, value): setattr(self, attr, value) return setMethod + def generateGetMethod(attr): def getMethod(self): return getattr(self, attr, None) return getMethod + def generateAddMethod(attr, factory, infos): def addMethod(self): if infos["type"] == ATTRIBUTE: @@ -1580,11 +1608,13 @@ raise ValueError("Invalid class attribute!") return addMethod + def generateDeleteMethod(attr): def deleteMethod(self): setattr(self, attr, None) return deleteMethod + def generateAppendMethod(attr, maxOccurs, factory, infos): def appendMethod(self, value): infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) @@ -1598,6 +1628,7 @@ raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr)) return appendMethod + def generateInsertMethod(attr, maxOccurs, factory, infos): def insertMethod(self, index, value): infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) @@ -1613,11 +1644,13 @@ raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr)) return insertMethod + def generateGetChoicesMethod(choice_types): def getChoicesMethod(self): return [choice["name"] for choice in choice_types] return getChoicesMethod + def generateSetChoiceByTypeMethod(factory, choice_types): choices = dict([(choice["name"], choice) for choice in choice_types]) def setChoiceMethod(self, content_type): @@ -1630,6 +1663,7 @@ return new_content return setChoiceMethod + def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types): choices = dict([(choice["name"], choice) for choice in choice_types]) def appendChoiceMethod(self, content_type): @@ -1645,6 +1679,7 @@ raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs) return appendChoiceMethod + def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types): choices = dict([(choice["name"], choice) for choice in choice_types]) def insertChoiceMethod(self, index, content_type): @@ -1660,6 +1695,7 @@ raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs) return insertChoiceMethod + def generateRemoveMethod(attr, minOccurs): def removeMethod(self, index): attr_list = getattr(self, attr) @@ -1669,6 +1705,7 @@ raise ValueError("There can't be less than %d values in \"%s\"!" % (minOccurs, attr)) return removeMethod + def generateCountMethod(attr): def countMethod(self): return len(getattr(self, attr)) @@ -1680,6 +1717,7 @@ NAMESPACE_PATTERN = re.compile("xmlns(?:\:[^\=]*)?=\"[^\"]*\" ") + class DefaultElementClass(etree.ElementBase): StructurePattern = re.compile("$") @@ -1693,6 +1731,7 @@ def tostring(self): return NAMESPACE_PATTERN.sub("", etree.tostring(self, pretty_print=True, encoding='utf-8')).decode('utf-8') + class XMLElementClassLookUp(etree.PythonElementClassLookup): def __init__(self, classes, *args, **kwargs): @@ -1727,6 +1766,7 @@ return element_class[0] return element_class + class XMLClassParser(etree.XMLParser): def __init__(self, namespaces, default_namespace_format, base_class, xsd_schema, *args, **kwargs): @@ -1789,6 +1829,7 @@ new_element._init_() return new_element + def GenerateParser(factory, xsdstring): ComputedClasses = factory.CreateClasses() diff -r c02818d7e29f -r 7e61baa047f0 xmlclass/xsdschema.py --- a/xmlclass/xsdschema.py Mon Aug 14 22:30:41 2017 +0300 +++ b/xmlclass/xsdschema.py Mon Aug 14 23:27:15 2017 +0300 @@ -30,9 +30,11 @@ from xmlclass import * + def GenerateDictFacets(facets): return dict([(name, (None, False)) for name in facets]) + def GenerateSimpleTypeXMLText(function): def generateXMLTextMethod(value, name=None, indent=0): text = "" @@ -45,6 +47,7 @@ return text return generateXMLTextMethod + def GenerateFloatXMLText(extra_values=[], decimal=None): float_format = (lambda x: "{:.{width}f}".format(x, width=decimal).rstrip('0') if decimal is not None else str) @@ -110,6 +113,7 @@ # Simple type elements + def GenerateFacetReducing(facetname, canbefixed): def ReduceFacet(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -486,6 +490,7 @@ simpleType["generate"] = GenerateSimpleType return simpleType + def ReduceSimpleType(factory, attributes, elements): # Reduce all the simple type children annotations, children = factory.ReduceElements(elements) @@ -497,6 +502,7 @@ # Complex type + def ExtractAttributes(factory, elements, base=None): attrs = [] attrnames = {} @@ -717,6 +723,7 @@ any.update(attributes) return any + def ReduceElement(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -771,6 +778,7 @@ else: raise ValueError("\"Element\" must have at least a \"ref\" or a \"name\" defined!") + def ReduceAll(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -867,6 +875,7 @@ # Constraint elements + def ReduceUnique(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -874,6 +883,7 @@ unique.update(attributes) return unique + def ReduceKey(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -881,6 +891,7 @@ key.update(attributes) return key + def ReduceKeyRef(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -888,6 +899,7 @@ keyref.update(attributes) return keyref + def ReduceSelector(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -895,6 +907,7 @@ selector.update(attributes) return selector + def ReduceField(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -909,6 +922,7 @@ annotations, children = factory.ReduceElements(elements) raise ValueError("\"import\" element isn't supported yet!") + def ReduceInclude(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) @@ -933,6 +947,7 @@ factory.EquivalentClassesParent.update(include_factory.EquivalentClassesParent) return None + def ReduceRedefine(factory, attributes, elements): annotations, children = factory.ReduceElements(elements) raise ValueError("\"redefine\" element isn't supported yet!") @@ -962,6 +977,7 @@ elif not CompareSchema(infos, child): raise ValueError("\"%s\" is defined twice in targetNamespace!" % child["name"]) + def CompareSchema(schema, reference): if isinstance(schema, ListType): if not isinstance(reference, ListType) or len(schema) != len(reference): @@ -1091,11 +1107,12 @@ return element_infos return None -""" -This function opens the xsd file and generate a xml parser with class lookup from -the xml tree -""" + def GenerateParserFromXSD(filepath): + """ + This function opens the xsd file and generate a xml parser with class lookup from + the xml tree + """ xsdfile = open(filepath, 'r') xsdstring = xsdfile.read() xsdfile.close() @@ -1105,10 +1122,11 @@ os.chdir(cwd) return parser -""" -This function generate a xml from the xsd given as a string -""" + def GenerateParserFromXSDstring(xsdstring): + """ + This function generate a xml from the xsd given as a string + """ return GenerateParser(XSDClassFactory(minidom.parseString(xsdstring)), xsdstring)