GetEditedElementInstancesInfos now optimized as well. Forgotten because not using [R.I.P]LibraryResolver, but still XSLT compiling was hapenning on each call.
authorEdouard Tisserant
Fri, 23 Feb 2018 11:16:25 +0100
changeset 1957 2d1cc4f5e4ef
parent 1956 2b90514edfbf
child 1958 67f0d7ff7d3e
GetEditedElementInstancesInfos now optimized as well. Forgotten because not using [R.I.P]LibraryResolver, but still XSLT compiling was hapenning on each call.
PLCControler.py
dialogs/ActionBlockDialog.py
plcopen/BlockInstanceCollector.py
plcopen/pou_block_instances.xslt
plcopen/pou_block_instances.ysl2
--- a/PLCControler.py	Tue Feb 20 15:09:01 2018 +0100
+++ b/PLCControler.py	Fri Feb 23 11:16:25 2018 +0100
@@ -31,9 +31,6 @@
 import re
 import datetime
 from time import localtime
-from collections import OrderedDict, namedtuple
-
-from lxml import etree
 
 import util.paths as paths
 from plcopen import *
@@ -42,6 +39,7 @@
 from plcopen.InstancesPathCollector import InstancesPathCollector
 from plcopen.POUVariablesCollector import POUVariablesCollector
 from plcopen.InstanceTagnameCollector import InstanceTagnameCollector
+from plcopen.BlockInstanceCollector import BlockInstanceCollector
 from plcopen.VariableInfoCollector import VariableInfoCollector
 from graphics.GraphicCommons import *
 from PLCGenerator import *
@@ -50,162 +48,6 @@
 
 ScriptDirectory = paths.AbsDir(__file__)
 
-# -------------------------------------------------------------------------------
-#           Helpers object for generating pou block instances list
-# -------------------------------------------------------------------------------
-
-
-_Point = namedtuple("Point", ["x", "y"])
-
-_BlockInstanceInfos = namedtuple(
-    "BlockInstanceInfos",
-    ["type", "id", "x", "y", "width", "height", "specific_values", "inputs", "outputs"])
-
-_BlockSpecificValues = (
-    namedtuple("BlockSpecificValues",
-               ["name", "execution_order"]),
-    [_StringValue, int])
-_VariableSpecificValues = (
-    namedtuple("VariableSpecificValues",
-               ["name", "value_type", "execution_order"]),
-    [_StringValue, _StringValue, int])
-_ConnectionSpecificValues = (
-    namedtuple("ConnectionSpecificValues", ["name"]),
-    [_StringValue])
-
-_PowerRailSpecificValues = (
-    namedtuple("PowerRailSpecificValues", ["connectors"]),
-    [int])
-
-_LDElementSpecificValues = (
-    namedtuple("LDElementSpecificValues",
-               ["name", "negated", "edge", "storage", "execution_order"]),
-    [_StringValue, _BoolValue, _StringValue, _StringValue, int])
-
-_DivergenceSpecificValues = (
-    namedtuple("DivergenceSpecificValues", ["connectors"]),
-    [int])
-
-_SpecificValuesTuples = {
-    "comment": (
-        namedtuple("CommentSpecificValues", ["content"]),
-        [_StringValue]),
-    "input": _VariableSpecificValues,
-    "output": _VariableSpecificValues,
-    "inout": _VariableSpecificValues,
-    "connector": _ConnectionSpecificValues,
-    "continuation": _ConnectionSpecificValues,
-    "leftPowerRail": _PowerRailSpecificValues,
-    "rightPowerRail": _PowerRailSpecificValues,
-    "contact": _LDElementSpecificValues,
-    "coil": _LDElementSpecificValues,
-    "step": (
-        namedtuple("StepSpecificValues", ["name", "initial", "action"]),
-        [_StringValue, _BoolValue, lambda x: x]),
-    "transition": (
-        namedtuple("TransitionSpecificValues",
-                   ["priority", "condition_type", "condition", "connection"]),
-        [int, _StringValue, _StringValue, lambda x: x]),
-    "selectionDivergence": _DivergenceSpecificValues,
-    "selectionConvergence": _DivergenceSpecificValues,
-    "simultaneousDivergence": _DivergenceSpecificValues,
-    "simultaneousConvergence": _DivergenceSpecificValues,
-    "jump": (
-        namedtuple("JumpSpecificValues", ["target"]),
-        [_StringValue]),
-    "actionBlock": (
-        namedtuple("ActionBlockSpecificValues", ["actions"]),
-        [lambda x: x]),
-}
-
-_InstanceConnectionInfos = namedtuple(
-    "InstanceConnectionInfos",
-    ["name", "negated", "edge", "position", "links"])
-
-_ConnectionLinkInfos = namedtuple(
-    "ConnectionLinkInfos",
-    ["refLocalId", "formalParameter", "points"])
-
-
-class _ActionInfos(object):
-    __slots__ = ["qualifier", "type", "value", "duration", "indicator"]
-
-    def __init__(self, *args):
-        for attr, value in zip(self.__slots__, args):
-            setattr(self, attr, value if value is not None else "")
-
-    def copy(self):
-        return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__])
-
-
-class BlockInstanceFactory(object):
-
-    def __init__(self, block_instances):
-        self.BlockInstances = block_instances
-        self.CurrentInstance = None
-        self.SpecificValues = None
-        self.CurrentConnection = None
-        self.CurrentLink = None
-
-    def SetSpecificValues(self, context, *args):
-        self.SpecificValues = list(args)
-        self.CurrentInstance = None
-        self.CurrentConnection = None
-        self.CurrentLink = None
-
-    def AddBlockInstance(self, context, *args):
-        specific_values_tuple, specific_values_translation = \
-            _SpecificValuesTuples.get(args[0][0], _BlockSpecificValues)
-
-        if args[0][0] == "step" and len(self.SpecificValues) < 3 or \
-           args[0][0] == "transition" and len(self.SpecificValues) < 4:
-            self.SpecificValues.append([None])
-        elif args[0][0] == "actionBlock" and len(self.SpecificValues) < 1:
-            self.SpecificValues.append([[]])
-        specific_values = specific_values_tuple(*_translate_args(
-            specific_values_translation, self.SpecificValues))
-        self.SpecificValues = None
-
-        self.CurrentInstance = _BlockInstanceInfos(
-            *(_translate_args([_StringValue, int] + [float] * 4, args) +
-              [specific_values, [], []]))
-
-        self.BlockInstances[self.CurrentInstance.id] = self.CurrentInstance
-
-    def AddInstanceConnection(self, context, *args):
-        connection_args = _translate_args(
-            [_StringValue] * 2 + [_BoolValue, _StringValue] + [float] * 2, args)
-
-        self.CurrentConnection = _InstanceConnectionInfos(
-            *(connection_args[1:4] + [
-                _Point(*connection_args[4:6]), []]))
-
-        if self.CurrentInstance is not None:
-            if connection_args[0] == "input":
-                self.CurrentInstance.inputs.append(self.CurrentConnection)
-            else:
-                self.CurrentInstance.outputs.append(self.CurrentConnection)
-        else:
-            self.SpecificValues.append([self.CurrentConnection])
-
-    def AddConnectionLink(self, context, *args):
-        self.CurrentLink = _ConnectionLinkInfos(
-            *(_translate_args([int, _StringValue], args) + [[]]))
-        self.CurrentConnection.links.append(self.CurrentLink)
-
-    def AddLinkPoint(self, context, *args):
-        self.CurrentLink.points.append(_Point(
-            *_translate_args([float] * 2, args)))
-
-    def AddAction(self, context, *args):
-        if len(self.SpecificValues) == 0:
-            self.SpecificValues.append([[]])
-        translated_args = _translate_args([_StringValue] * 5, args)
-        self.SpecificValues[0][0].append(_ActionInfos(*translated_args))
-
-
-pou_block_instances_xslt = etree.parse(
-    os.path.join(ScriptDirectory, "plcopen", "pou_block_instances.xslt"))
 
 
 # Length of the buffer
@@ -308,6 +150,7 @@
         self.InstancesPathCollector = InstancesPathCollector(self)
         self.POUVariablesCollector = POUVariablesCollector(self)
         self.InstanceTagnameCollector = InstanceTagnameCollector(self)
+        self.BlockInstanceCollector = BlockInstanceCollector(self)
         self.VariableInfoCollector = VariableInfoCollector(self)
 
     # Reset PLCControler internal variables
@@ -2112,21 +1955,10 @@
             return new_id, connections
 
     def GetEditedElementInstancesInfos(self, tagname, debug=False):
-        element_instances = OrderedDict()
         element = self.GetEditedElement(tagname, debug)
         if element is not None:
-            factory = BlockInstanceFactory(element_instances)
-
-            pou_block_instances_xslt_tree = etree.XSLT(
-                pou_block_instances_xslt,
-                extensions={
-                    ("pou_block_instances_ns", name): getattr(factory, name)
-                    for name in ["AddBlockInstance", "SetSpecificValues",
-                                 "AddInstanceConnection", "AddConnectionLink",
-                                 "AddLinkPoint", "AddAction"]})
-
-            pou_block_instances_xslt_tree(element)
-        return element_instances
+            return self.BlockInstanceCollector.Collect(element, debug)
+        return {}
 
     def ClearEditedElementExecutionOrder(self, tagname):
         element = self.GetEditedElement(tagname)
--- a/dialogs/ActionBlockDialog.py	Tue Feb 20 15:09:01 2018 +0100
+++ b/dialogs/ActionBlockDialog.py	Fri Feb 23 11:16:25 2018 +0100
@@ -29,7 +29,7 @@
 import wx.lib.buttons
 
 from controls import CustomGrid, CustomTable
-from PLCControler import _ActionInfos
+from plcopen.BlockInstanceCollector import _ActionInfos
 from util.BitmapLibrary import GetBitmap
 from util.TranslationCatalogs import NoTranslate
 # -------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plcopen/BlockInstanceCollector.py	Fri Feb 23 11:16:25 2018 +0100
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# This file is part of Beremiz.
+# See COPYING file for copyrights details.
+
+from __future__ import absolute_import
+from plcopen.XSLTModelQuery import XSLTModelQuery, _StringValue, _BoolValue, _translate_args
+from collections import OrderedDict, namedtuple
+
+# -------------------------------------------------------------------------------
+#           Helpers object for generating pou block instances list
+# -------------------------------------------------------------------------------
+
+
+_Point = namedtuple("Point", ["x", "y"])
+
+_BlockInstanceInfos = namedtuple(
+    "BlockInstanceInfos",
+    ["type", "id", "x", "y", "width", "height", "specific_values", "inputs", "outputs"])
+
+_BlockSpecificValues = (
+    namedtuple("BlockSpecificValues",
+               ["name", "execution_order"]),
+    [_StringValue, int])
+_VariableSpecificValues = (
+    namedtuple("VariableSpecificValues",
+               ["name", "value_type", "execution_order"]),
+    [_StringValue, _StringValue, int])
+_ConnectionSpecificValues = (
+    namedtuple("ConnectionSpecificValues", ["name"]),
+    [_StringValue])
+
+_PowerRailSpecificValues = (
+    namedtuple("PowerRailSpecificValues", ["connectors"]),
+    [int])
+
+_LDElementSpecificValues = (
+    namedtuple("LDElementSpecificValues",
+               ["name", "negated", "edge", "storage", "execution_order"]),
+    [_StringValue, _BoolValue, _StringValue, _StringValue, int])
+
+_DivergenceSpecificValues = (
+    namedtuple("DivergenceSpecificValues", ["connectors"]),
+    [int])
+
+_SpecificValuesTuples = {
+    "comment": (
+        namedtuple("CommentSpecificValues", ["content"]),
+        [_StringValue]),
+    "input": _VariableSpecificValues,
+    "output": _VariableSpecificValues,
+    "inout": _VariableSpecificValues,
+    "connector": _ConnectionSpecificValues,
+    "continuation": _ConnectionSpecificValues,
+    "leftPowerRail": _PowerRailSpecificValues,
+    "rightPowerRail": _PowerRailSpecificValues,
+    "contact": _LDElementSpecificValues,
+    "coil": _LDElementSpecificValues,
+    "step": (
+        namedtuple("StepSpecificValues", ["name", "initial", "action"]),
+        [_StringValue, _BoolValue, lambda x: x]),
+    "transition": (
+        namedtuple("TransitionSpecificValues",
+                   ["priority", "condition_type", "condition", "connection"]),
+        [int, _StringValue, _StringValue, lambda x: x]),
+    "selectionDivergence": _DivergenceSpecificValues,
+    "selectionConvergence": _DivergenceSpecificValues,
+    "simultaneousDivergence": _DivergenceSpecificValues,
+    "simultaneousConvergence": _DivergenceSpecificValues,
+    "jump": (
+        namedtuple("JumpSpecificValues", ["target"]),
+        [_StringValue]),
+    "actionBlock": (
+        namedtuple("ActionBlockSpecificValues", ["actions"]),
+        [lambda x: x]),
+}
+
+_InstanceConnectionInfos = namedtuple(
+    "InstanceConnectionInfos",
+    ["name", "negated", "edge", "position", "links"])
+
+_ConnectionLinkInfos = namedtuple(
+    "ConnectionLinkInfos",
+    ["refLocalId", "formalParameter", "points"])
+
+
+class _ActionInfos(object):
+    __slots__ = ["qualifier", "type", "value", "duration", "indicator"]
+
+    def __init__(self, *args):
+        for attr, value in zip(self.__slots__, args):
+            setattr(self, attr, value if value is not None else "")
+
+    def copy(self):
+        return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__])
+
+
+class BlockInstanceFactory(object):
+
+    def __init__(self, block_instances):
+        self.BlockInstances = block_instances
+        self.CurrentInstance = None
+        self.SpecificValues = None
+        self.CurrentConnection = None
+        self.CurrentLink = None
+
+    def SetSpecificValues(self, context, *args):
+        self.SpecificValues = list(args)
+        self.CurrentInstance = None
+        self.CurrentConnection = None
+        self.CurrentLink = None
+
+    def AddBlockInstance(self, context, *args):
+        specific_values_tuple, specific_values_translation = \
+            _SpecificValuesTuples.get(args[0][0], _BlockSpecificValues)
+
+        if args[0][0] == "step" and len(self.SpecificValues) < 3 or \
+           args[0][0] == "transition" and len(self.SpecificValues) < 4:
+            self.SpecificValues.append([None])
+        elif args[0][0] == "actionBlock" and len(self.SpecificValues) < 1:
+            self.SpecificValues.append([[]])
+        specific_values = specific_values_tuple(*_translate_args(
+            specific_values_translation, self.SpecificValues))
+        self.SpecificValues = None
+
+        self.CurrentInstance = _BlockInstanceInfos(
+            *(_translate_args([_StringValue, int] + [float] * 4, args) +
+              [specific_values, [], []]))
+
+        self.BlockInstances[self.CurrentInstance.id] = self.CurrentInstance
+
+    def AddInstanceConnection(self, context, *args):
+        connection_args = _translate_args(
+            [_StringValue] * 2 + [_BoolValue, _StringValue] + [float] * 2, args)
+
+        self.CurrentConnection = _InstanceConnectionInfos(
+            *(connection_args[1:4] + [
+                _Point(*connection_args[4:6]), []]))
+
+        if self.CurrentInstance is not None:
+            if connection_args[0] == "input":
+                self.CurrentInstance.inputs.append(self.CurrentConnection)
+            else:
+                self.CurrentInstance.outputs.append(self.CurrentConnection)
+        else:
+            self.SpecificValues.append([self.CurrentConnection])
+
+    def AddConnectionLink(self, context, *args):
+        self.CurrentLink = _ConnectionLinkInfos(
+            *(_translate_args([int, _StringValue], args) + [[]]))
+        self.CurrentConnection.links.append(self.CurrentLink)
+
+    def AddLinkPoint(self, context, *args):
+        self.CurrentLink.points.append(_Point(
+            *_translate_args([float] * 2, args)))
+
+    def AddAction(self, context, *args):
+        if len(self.SpecificValues) == 0:
+            self.SpecificValues.append([[]])
+        translated_args = _translate_args([_StringValue] * 5, args)
+        self.SpecificValues[0][0].append(_ActionInfos(*translated_args))
+
+
+class BlockInstanceCollector(XSLTModelQuery):
+    """ object for collecting instances path list"""
+    def __init__(self, controller):
+        XSLTModelQuery.__init__(self,
+                                controller,
+                                "pou_block_instances.xslt",
+                                [(name, self.FactoryCaller(name))
+                                 for name in ["AddBlockInstance",
+                                              "SetSpecificValues",
+                                              "AddInstanceConnection",
+                                              "AddConnectionLink",
+                                              "AddLinkPoint",
+                                              "AddAction"]])
+
+    def FactoryCaller(self, funcname):
+        def CallFactory(*args):
+            return getattr(self.factory, funcname)(*args)
+        return CallFactory
+
+    def Collect(self, root, debug):
+        element_instances = OrderedDict()
+        self.factory = BlockInstanceFactory(element_instances)
+        self._process_xslt(root, debug)
+        self.factory = None
+        return element_instances
--- a/plcopen/pou_block_instances.xslt	Tue Feb 20 15:09:01 2018 +0100
+++ b/plcopen/pou_block_instances.xslt	Fri Feb 23 11:16:25 2018 +0100
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<xsl:stylesheet xmlns:exsl="http://exslt.org/common" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:ppx="http://www.plcopen.org/xml/tc6_0201" xmlns:ns="pou_block_instances_ns" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="ns" version="1.0" exclude-result-prefixes="ns">
+<xsl:stylesheet xmlns:exsl="http://exslt.org/common" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:ppx="http://www.plcopen.org/xml/tc6_0201" xmlns:ns="beremiz" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="ns" version="1.0" exclude-result-prefixes="ns">
   <xsl:output method="xml"/>
   <xsl:template match="text()"/>
   <xsl:template match="ppx:pou[ppx:body]|ppx:transition[ppx:body]|ppx:action[ppx:body]">
--- a/plcopen/pou_block_instances.ysl2	Tue Feb 20 15:09:01 2018 +0100
+++ b/plcopen/pou_block_instances.ysl2	Fri Feb 23 11:16:25 2018 +0100
@@ -1,7 +1,7 @@
 include yslt_noindent.yml2
 istylesheet xmlns:ppx="http://www.plcopen.org/xml/tc6_0201"
             xmlns:xhtml="http://www.w3.org/1999/xhtml"
-            xmlns:ns="pou_block_instances_ns" 
+            xmlns:ns="beremiz" 
             extension-element-prefixes="ns" 
             exclude-result-prefixes="ns" {