# HG changeset patch # User Andrey Skvortsov # Date 1533912333 -10800 # Node ID a3ac46366b86a0b237dac93be6b2281ac70b98a8 # Parent 068ccc02f5f2d58df9eaede32c56e9564b20e5be Dirty fix for error '_object_has_no_attribute_'getSlave' in EtherCAT extension traceback: File "/home/developer/WorkData/PLC/beremiz/beremiz/IDEFrame.py", line 1433, in OnPouSelectedChanged window.RefreshView() File "/home/developer/WorkData/PLC/beremiz/beremiz/etherlab/ConfigEditor.py", line 837, in RefreshView self.RefreshProcessVariables() File "/home/developer/WorkData/PLC/beremiz/beremiz/etherlab/ConfigEditor.py", line 886, in RefreshProcessVariables slaves = self.Controler.GetSlaves(**self.CurrentNodesFilter) File "/home/developer/WorkData/PLC/beremiz/beremiz/etherlab/EthercatMaster.py", line 341, in GetSlaves for slave in self.Config.getConfig().getSlave(): :_'lxml.etree._Element'_object_has_no_attribute_'getSlave' Steps to reproduce problem: - Add new EtherCAT master - Add new EthercatNode to the master - double click on this is looks like dirty hack to fix strange problem with initial[0] changing its type after returning from _init_ method to lxml.etree._Element As a result all methods generated by class factory are lost. For example, in function initMethod initial[0].__class__ points to xmlclass.xmlclass.Config. After map(self.append, initial) self.Config.__class__ is 'xmlclass.xmlclass.Config' as well. But after returning from initMethod (_init) in CreateElement self.Config.__class__ has changed to lxml.etree._Element. I've noticed similar behavior if copy/deepcopy is used for any child of etree.ElementBase. See simple example below. [-------------------------------------------------------------] #!/usr/bin/python from __future__ import print_function from lxml import etree import copy class DefaultElementClass(etree.ElementBase): def getLocalTag(self): return etree.QName(self.tag).localname def printInformation(x): print(x, x.__class__, "getLocalTag" in dir(x)) a = DefaultElementClass() printInformation(a) # printInformation(copy.copy(a)) printInformation(copy.deepcopy(a)) [-------------------------------------------------------------] diff -r 068ccc02f5f2 -r a3ac46366b86 xmlclass/xmlclass.py --- a/xmlclass/xmlclass.py Fri Aug 10 15:58:40 2018 +0300 +++ b/xmlclass/xmlclass.py Fri Aug 10 17:45:33 2018 +0300 @@ -1162,6 +1162,7 @@ classmembers["get%s" % elmtname] = generateGetMethod(elmtname) classmembers["_init_"] = generateInitMethod(self, classinfos) + classmembers["_tmp_initial_"] = None classmembers["StructurePattern"] = GetStructurePattern(classinfos) classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos) classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos) @@ -1581,6 +1582,10 @@ if element["type"] != CHOICE: initial = GetElementInitialValue(factory, element) if initial is not None: + # FIXME: this is looks like dirty hack to fix strange problem with initial[0] + # changing its type after returning from _init_ method to lxml.etree._Element + # As a result all methods generated by class factory are lost. + object.__setattr__(self, "_tmp_initial_", initial) map(self.append, initial) return initMethod