GetVariableDictionary and GetPouInterfaceReturnType optimized with new VariableInfoCollector based on XSLTModelQuery. Moved corresponding definitions out of PLCControler.py.
authorEdouard Tisserant
Tue, 20 Feb 2018 11:24:10 +0100
changeset 1951 bbd1e1744c91
parent 1950 752ec68da94d
child 1952 0c20fc810d61
GetVariableDictionary and GetPouInterfaceReturnType optimized with new VariableInfoCollector based on XSLTModelQuery. Moved corresponding definitions out of PLCControler.py.
PLCControler.py
controls/VariablePanel.py
plcopen/VariableInfoCollector.py
plcopen/variables_infos.xslt
plcopen/variables_infos.ysl2
--- a/PLCControler.py	Mon Feb 19 15:46:50 2018 +0100
+++ b/PLCControler.py	Tue Feb 20 11:24:10 2018 +0100
@@ -43,6 +43,7 @@
 from plcopen.InstancesPathCollector import InstancesPathCollector
 from plcopen.POUVariablesCollector import POUVariablesCollector
 from plcopen.InstanceTagnameCollector import InstanceTagnameCollector
+from plcopen.VariableInfoCollector import VariableInfoCollector
 from graphics.GraphicCommons import *
 from PLCGenerator import *
 
@@ -74,60 +75,6 @@
 
 
 # -------------------------------------------------------------------------------
-#                 Helpers object for generating pou var list
-# -------------------------------------------------------------------------------
-
-
-class _VariableInfos(object):
-    __slots__ = ["Name", "Class", "Option", "Location", "InitialValue",
-                 "Edit", "Documentation", "Type", "Tree", "Number"]
-
-    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 _VariableInfos(*[getattr(self, attr) for attr in self.__slots__])
-
-
-class VariablesInfosFactory(object):
-
-    def __init__(self, variables):
-        self.Variables = variables
-        self.TreeStack = []
-        self.Type = None
-        self.Dimensions = None
-
-    def SetType(self, context, *args):
-        self.Type = args[0][0]
-
-    def GetType(self):
-        if len(self.Dimensions) > 0:
-            return ("array", self.Type, self.Dimensions)
-        return self.Type
-
-    def GetTree(self):
-        return (self.TreeStack.pop(-1), self.Dimensions)
-
-    def AddDimension(self, context, *args):
-        self.Dimensions.append(tuple(
-            _translate_args([_StringValue] * 2, args)))
-
-    def AddTree(self, context, *args):
-        self.TreeStack.append([])
-        self.Dimensions = []
-
-    def AddVarToTree(self, context, *args):
-        var = (args[0][0], self.Type, self.GetTree())
-        self.TreeStack[-1].append(var)
-
-    def AddVariable(self, context, *args):
-        self.Variables.append(_VariableInfos(*(
-            _translate_args([_StringValue] * 5 + [_BoolValue] + [_StringValue], args) +
-            [self.GetType(), self.GetTree()])))
-
-
-# -------------------------------------------------------------------------------
 #           Helpers object for generating pou block instances list
 # -------------------------------------------------------------------------------
 
@@ -385,6 +332,7 @@
         self.InstancesPathCollector = InstancesPathCollector(self)
         self.POUVariablesCollector = POUVariablesCollector(self)
         self.InstanceTagnameCollector = InstanceTagnameCollector(self)
+        self.VariableInfoCollector = VariableInfoCollector(self)
 
     # Reset PLCControler internal variables
     def Reset(self):
@@ -1162,21 +1110,8 @@
 
     def GetVariableDictionary(self, object_with_vars, tree=False, debug=False):
         variables = []
-        factory = VariablesInfosFactory(variables)
-
-        parser = etree.XMLParser()
-        parser.resolvers.add(LibraryResolver(self, debug))
-
-        variables_infos_xslt_tree = etree.XSLT(
-            etree.parse(
-                os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"),
-                parser),
-            extensions={("var_infos_ns", name): getattr(factory, name)
-                        for name in ["SetType", "AddDimension", "AddTree",
-                                     "AddVarToTree", "AddVariable"]})
-        variables_infos_xslt_tree(
-            object_with_vars, tree=etree.XSLT.strparam(str(tree)))
-
+        factory = self.VariableInfoCollector.Collect(object_with_vars,
+                                                     debug, variables, tree)
         return variables
 
     # Add a global var to configuration to configuration
@@ -1329,20 +1264,8 @@
             # Return the return type if there is one
             return_type = pou.interface.getreturnType()
             if return_type is not None:
-                factory = VariablesInfosFactory([])
-
-                parser = etree.XMLParser()
-                parser.resolvers.add(LibraryResolver(self))
-
-                return_type_infos_xslt_tree = etree.XSLT(
-                    etree.parse(
-                        os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"),
-                        parser),
-                    extensions={("var_infos_ns", name): getattr(factory, name)
-                                for name in ["SetType", "AddDimension",
-                                             "AddTree", "AddVarToTree"]})
-                return_type_infos_xslt_tree(
-                    return_type, tree=etree.XSLT.strparam(str(tree)))
+                factory = self.VariableInfoCollector.Collect(return_type, 
+                                                             debug, [], tree)
                 if tree:
                     return [factory.GetType(), factory.GetTree()]
                 return factory.GetType()
--- a/controls/VariablePanel.py	Mon Feb 19 15:46:50 2018 +0100
+++ b/controls/VariablePanel.py	Tue Feb 20 11:24:10 2018 +0100
@@ -39,7 +39,7 @@
 from controls.LocationCellEditor import LocationCellEditor
 from util.BitmapLibrary import GetBitmap
 from util.TranslationCatalogs import NoTranslate
-from PLCControler import _VariableInfos
+from plcopen.VariableInfoCollector import _VariableInfos
 
 
 # -------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plcopen/VariableInfoCollector.py	Tue Feb 20 11:24:10 2018 +0100
@@ -0,0 +1,87 @@
+#!/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
+
+# -------------------------------------------------------------------------------
+#                 Helpers object for generating pou var list
+# -------------------------------------------------------------------------------
+
+class _VariableInfos(object):
+    __slots__ = ["Name", "Class", "Option", "Location", "InitialValue",
+                 "Edit", "Documentation", "Type", "Tree", "Number"]
+
+    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 _VariableInfos(*[getattr(self, attr) for attr in self.__slots__])
+
+
+class VariablesInfosFactory(object):
+    """ Helpers object for generating pou var list """
+
+    def __init__(self, variables):
+        self.Variables = variables
+        self.TreeStack = []
+        self.Type = None
+        self.Dimensions = None
+
+    def SetType(self, context, *args):
+        self.Type = args[0][0]
+
+    def GetType(self):
+        if len(self.Dimensions) > 0:
+            return ("array", self.Type, self.Dimensions)
+        return self.Type
+
+    def GetTree(self):
+        return (self.TreeStack.pop(-1), self.Dimensions)
+
+    def AddDimension(self, context, *args):
+        self.Dimensions.append(tuple(
+            _translate_args([_StringValue] * 2, args)))
+
+    def AddTree(self, context, *args):
+        self.TreeStack.append([])
+        self.Dimensions = []
+
+    def AddVarToTree(self, context, *args):
+        var = (args[0][0], self.Type, self.GetTree())
+        self.TreeStack[-1].append(var)
+
+    def AddVariable(self, context, *args):
+        self.Variables.append(_VariableInfos(*(
+            _translate_args([_StringValue] * 5 + [_BoolValue] + [_StringValue], args) +
+            [self.GetType(), self.GetTree()])))
+
+
+class VariableInfoCollector(XSLTModelQuery):
+    def __init__(self, controller):
+        XSLTModelQuery.__init__(self,
+                                controller,
+                                "variables_infos.xslt",
+                                [(name, self.FactoryCaller(name)) 
+                                    for name in [
+                                        "SetType",
+                                        "AddDimension",
+                                        "AddTree",
+                                        "AddVarToTree",
+                                        "AddVariable"]])
+
+    def FactoryCaller(self, funcname):
+        def CallFactory(*args):
+            return getattr(self.factory, funcname)(*args)
+        return CallFactory
+
+    def Collect(self, root, debug, variables, tree):
+        self.factory = VariablesInfosFactory(variables)
+        self._process_xslt(root, debug, tree=str(tree))
+        res = self.factory
+        self.factory = None
+        return res
+
--- a/plcopen/variables_infos.xslt	Mon Feb 19 15:46:50 2018 +0100
+++ b/plcopen/variables_infos.xslt	Tue Feb 20 11:24:10 2018 +0100
@@ -1,17 +1,12 @@
 <?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="var_infos_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:param name="tree"/>
   <xsl:template match="text()"/>
-  <xsl:variable name="project">
-    <xsl:copy-of select="document('project')/project/*"/>
-  </xsl:variable>
-  <xsl:variable name="stdlib">
-    <xsl:copy-of select="document('stdlib')/stdlib/*"/>
-  </xsl:variable>
-  <xsl:variable name="extensions">
-    <xsl:copy-of select="document('extensions')/extensions/*"/>
-  </xsl:variable>
+  <xsl:variable name="project" select="ns:GetProject()"/>
+  <xsl:variable name="stdlib" select="ns:GetStdLibs()"/>
+  <xsl:variable name="extensions" select="ns:GetExtensions()"/>
+  <xsl:variable name="all_types" select="($project | $stdlib | $extensions)/ppx:types"/>
   <xsl:template match="ppx:configuration">
     <xsl:apply-templates select="ppx:globalVars"/>
   </xsl:template>
@@ -131,7 +126,7 @@
     </xsl:variable>
     <xsl:choose>
       <xsl:when test="$tree='True'">
-        <xsl:apply-templates mode="var_type" select="exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                         exsl:node-set($project)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |&#10;                         exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                         exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |&#10;                         exsl:node-set($extensions)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                         exsl:node-set($extensions)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name]"/>
+        <xsl:apply-templates mode="var_type" select="$all_types/ppx:pous/ppx:pou[@name=$type_name] |                          $all_types/ppx:dataTypes/ppx:dataType[@name=$type_name]"/>
       </xsl:when>
     </xsl:choose>
     <xsl:value-of select="ns:SetType($type_name)"/>
@@ -170,9 +165,7 @@
     <xsl:variable name="type_name">
       <xsl:value-of select="@name"/>
     </xsl:variable>
-    <xsl:variable name="pou_infos">
-      <xsl:copy-of select="exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                    exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                    exsl:node-set($extensions)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]"/>
-    </xsl:variable>
+    <xsl:variable name="pou_infos" select="$all_types/ppx:pous/ppx:pou[@name=$type_name]"/>
     <xsl:choose>
       <xsl:when test="$pou_infos != ''">
         <xsl:text>false</xsl:text>
--- a/plcopen/variables_infos.ysl2	Mon Feb 19 15:46:50 2018 +0100
+++ b/plcopen/variables_infos.ysl2	Tue Feb 20 11:24:10 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="var_infos_ns" 
+            xmlns:ns="beremiz" 
             extension-element-prefixes="ns" 
             exclude-result-prefixes="ns" {
     
@@ -9,17 +9,14 @@
     
     template "text()";
     
-    variable "project" {
-        copy "document('project')/project/*";
-    }
-    
-    variable "stdlib" {
-        copy "document('stdlib')/stdlib/*";
-    }
-    variable "extensions" {
-        copy "document('extensions')/extensions/*";
-    }
-    
+    variable "project", "ns:GetProject()";
+    
+    variable "stdlib", "ns:GetStdLibs()";
+
+    variable "extensions", "ns:GetExtensions()";
+
+    variable "all_types", "($project | $stdlib | $extensions)/ppx:types";
+
     template "ppx:configuration" {
         apply "ppx:globalVars";
     }
@@ -129,12 +126,8 @@
         variable "type_name" > «@name»
         choose {
             when "$tree='True'" {
-                apply """exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
-                         exsl:node-set($project)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |
-                         exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
-                         exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |
-                         exsl:node-set($extensions)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
-                         exsl:node-set($extensions)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name]""", mode="var_type";
+                apply """$all_types/ppx:pous/ppx:pou[@name=$type_name] | \
+                         $all_types/ppx:dataTypes/ppx:dataType[@name=$type_name]""", mode="var_type";
             }
         }
         value "ns:SetType($type_name)";
@@ -166,11 +159,7 @@
     
     template "*[self::ppx:type or self::ppx:baseType or self::ppx:returnType]/ppx:derived", mode="var_edit" {
         variable "type_name" > «@name»
-        variable "pou_infos" {
-            copy """exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
-                    exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
-                    exsl:node-set($extensions)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]""";
-        }
+        variable "pou_infos", "$all_types/ppx:pous/ppx:pou[@name=$type_name]";
         choose {
             when "$pou_infos != ''" > false
             otherwise > true