automated conversion using 2to3-3.9 tool python3
authorGP Orcullo <kinsamanka@gmail.com>
Fri, 28 Oct 2022 12:39:15 +0800
branchpython3
changeset 3750 f62625418bff
parent 3749 fda6c1a37662
child 3751 a80a66ba52d6
automated conversion using 2to3-3.9 tool

cmd used: 2to3-3.9 -w <file>
Beremiz.py
BeremizIDE.py
Beremiz_service.py
CLIController.py
CodeFileTreeNode.py
ConfigTreeNode.py
IDEFrame.py
NativeLib.py
PLCControler.py
PLCGenerator.py
PLCOpenEditor.py
POULibrary.py
PSKManagement.py
ProjectController.py
XSLTransform.py
bacnet/__init__.py
bacnet/bacnet.py
c_ext/CFileEditor.py
c_ext/__init__.py
c_ext/c_ext.py
canfestival/NetworkEditor.py
canfestival/SlaveEditor.py
canfestival/__init__.py
canfestival/canfestival.py
canfestival/config_utils.py
connectors/ConnectorBase.py
connectors/PYRO/PSK_Adapter.py
connectors/PYRO/__init__.py
connectors/PYRO_dialog.py
connectors/SchemeEditor.py
connectors/WAMP/__init__.py
connectors/WAMP_dialog.py
connectors/__init__.py
controls/CustomEditableListBox.py
controls/CustomGrid.py
controls/CustomIntCtrl.py
controls/CustomStyledTextCtrl.py
controls/CustomTable.py
controls/CustomToolTip.py
controls/CustomTree.py
controls/DebugVariablePanel/DebugVariableGraphicViewer.py
controls/DebugVariablePanel/DebugVariableItem.py
controls/DebugVariablePanel/DebugVariablePanel.py
controls/DebugVariablePanel/DebugVariableTextViewer.py
controls/DebugVariablePanel/DebugVariableViewer.py
controls/DebugVariablePanel/GraphButton.py
controls/DebugVariablePanel/RingBuffer.py
controls/DebugVariablePanel/__init__.py
controls/DiscoveryPanel.py
controls/DurationCellEditor.py
controls/EnhancedStatusBar.py
controls/FolderTree.py
controls/IDBrowser.py
controls/LibraryPanel.py
controls/LocationCellEditor.py
controls/LogViewer.py
controls/PouInstanceVariablesPanel.py
controls/ProjectPropertiesPanel.py
controls/SearchResultPanel.py
controls/TextCtrlAutoComplete.py
controls/VariablePanel.py
controls/__init__.py
dialogs/AboutDialog.py
dialogs/ActionBlockDialog.py
dialogs/ArrayTypeDialog.py
dialogs/BlockPreviewDialog.py
dialogs/BrowseLocationsDialog.py
dialogs/BrowseValuesLibraryDialog.py
dialogs/CommentEditDialog.py
dialogs/ConnectionDialog.py
dialogs/DurationEditorDialog.py
dialogs/FBDBlockDialog.py
dialogs/FBDVariableDialog.py
dialogs/FindInPouDialog.py
dialogs/ForceVariableDialog.py
dialogs/IDManager.py
dialogs/IDMergeDialog.py
dialogs/LDElementDialog.py
dialogs/LDPowerRailDialog.py
dialogs/MessageBoxOnce.py
dialogs/PouActionDialog.py
dialogs/PouDialog.py
dialogs/PouNameDialog.py
dialogs/PouTransitionDialog.py
dialogs/ProjectDialog.py
dialogs/SFCDivergenceDialog.py
dialogs/SFCStepDialog.py
dialogs/SFCStepNameDialog.py
dialogs/SFCTransitionDialog.py
dialogs/SearchInProjectDialog.py
dialogs/UriEditor.py
dialogs/__init__.py
docutil/__init__.py
docutil/dochtml.py
docutil/docpdf.py
docutil/docsvg.py
editors/CodeFileEditor.py
editors/ConfTreeNodeEditor.py
editors/DataTypeEditor.py
editors/DebugViewer.py
editors/EditorPanel.py
editors/FileManagementPanel.py
editors/IECCodeViewer.py
editors/LDViewer.py
editors/ProjectNodeEditor.py
editors/ResourceEditor.py
editors/SFCViewer.py
editors/TextViewer.py
editors/Viewer.py
etherlab/ConfigEditor.py
etherlab/EtherCATManagementEditor.py
etherlab/EthercatCIA402Slave.py
etherlab/EthercatMaster.py
etherlab/EthercatSlave.py
etherlab/__init__.py
etherlab/runtime_etherlab.py
graphics/DebugDataConsumer.py
graphics/FBD_Objects.py
graphics/GraphicCommons.py
graphics/LD_Objects.py
graphics/RubberBand.py
graphics/SFC_Objects.py
graphics/ToolTipProducer.py
i18n/mki18n.py
modbus/mb_utils.py
modbus/modbus.py
opc_ua/__init__.py
opc_ua/client.py
opc_ua/opcua_client_maker.py
plcopen/BlockInstanceCollector.py
plcopen/InstanceTagnameCollector.py
plcopen/InstancesPathCollector.py
plcopen/POUVariablesCollector.py
plcopen/VariableInfoCollector.py
plcopen/XSLTModelQuery.py
plcopen/__init__.py
plcopen/definitions.py
plcopen/plcopen.py
plcopen/structures.py
plcopen/types_enums.py
py_ext/PythonEditor.py
py_ext/PythonFileCTNMixin.py
py_ext/__init__.py
py_ext/py_ext.py
runtime/NevowServer.py
runtime/PLCObject.py
runtime/PyroServer.py
runtime/ServicePublisher.py
runtime/Stunnel.py
runtime/WampClient.py
runtime/Worker.py
runtime/__init__.py
runtime/monotonic_time.py
runtime/spawn_subprocess.py
runtime/typemapping.py
runtime/xenomai.py
svghmi/__init__.py
svghmi/hmi_tree.py
svghmi/i18n.py
svghmi/svghmi.py
svghmi/svghmi_server.py
svghmi/ui.py
targets/Generic/__init__.py
targets/Linux/__init__.py
targets/Win32/__init__.py
targets/Xenomai/__init__.py
targets/__init__.py
targets/toolchain_gcc.py
targets/toolchain_makefile.py
tests/ide_tests/conftest.py
tests/ide_tests/load_and_build_tests.pytest/test_application.py
tests/ide_tests/wx_widgets.pytest/test_CustomIntCtrl.py
util/BitmapLibrary.py
util/ExceptionHandler.py
util/MiniTextControler.py
util/ProcessLogger.py
util/TranslationCatalogs.py
util/misc.py
util/paths.py
version.py
wxglade_hmi/__init__.py
wxglade_hmi/wxglade_hmi.py
xmlclass/__init__.py
xmlclass/xmlclass.py
xmlclass/xsdschema.py
--- a/Beremiz.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/Beremiz.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import sys
 import getopt
@@ -158,7 +158,7 @@
             sys.path.append(extension_folder)
             AddCatalog(os.path.join(extension_folder, "locale"))
             AddBitmapFolder(os.path.join(extension_folder, "images"))
-            execfile(extfilename, self.globals())
+            exec(compile(open(extfilename, "rb").read(), extfilename, 'exec'), self.globals())
 
     def CheckUpdates(self):
         if self.updateinfo_url is not None:
@@ -166,8 +166,8 @@
 
             def updateinfoproc():
                 try:
-                    import urllib2
-                    self.updateinfo = urllib2.urlopen(self.updateinfo_url, None).read()
+                    import urllib.request, urllib.error, urllib.parse
+                    self.updateinfo = urllib.request.urlopen(self.updateinfo_url, None).read()
                 except Exception:
                     self.updateinfo = _("update info unavailable.")
 
--- a/BeremizIDE.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/BeremizIDE.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import sys
 import shutil
@@ -246,9 +246,9 @@
 
     def _init_coll_FileMenu_Items(self, parent):
         AppendMenu(parent, help='', id=wx.ID_NEW,
-                   kind=wx.ITEM_NORMAL, text=_(u'New') + '\tCTRL+N')
+                   kind=wx.ITEM_NORMAL, text=_('New') + '\tCTRL+N')
         AppendMenu(parent, help='', id=wx.ID_OPEN,
-                   kind=wx.ITEM_NORMAL, text=_(u'Open') + '\tCTRL+O')
+                   kind=wx.ITEM_NORMAL, text=_('Open') + '\tCTRL+O')
         parent.Append(ID_FILEMENURECENTPROJECTS, _("&Recent Projects"), self.RecentProjectsMenu)
         parent.AppendSeparator()
         parent.Append(wx.ID_ANY, _("&Tutorials and Examples"), self.TutorialsProjectsMenu)
@@ -257,7 +257,7 @@
         project_list = sorted(os.listdir(exemples_dir))
 
         for idx, dirname  in enumerate(project_list):
-            text = u'&%d: %s' % (idx + 1, dirname)
+            text = '&%d: %s' % (idx + 1, dirname)
 
             item = self.TutorialsProjectsMenu.Append(wx.ID_ANY, text, '')
 
@@ -274,23 +274,23 @@
             self.Bind(wx.EVT_MENU, OpenExemple, item)
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_SAVE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Save') + '\tCTRL+S')
+                   kind=wx.ITEM_NORMAL, text=_('Save') + '\tCTRL+S')
         AppendMenu(parent, help='', id=wx.ID_SAVEAS,
-                   kind=wx.ITEM_NORMAL, text=_(u'Save as') + '\tCTRL+SHIFT+S')
+                   kind=wx.ITEM_NORMAL, text=_('Save as') + '\tCTRL+SHIFT+S')
         AppendMenu(parent, help='', id=wx.ID_CLOSE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Close Tab') + '\tCTRL+W')
+                   kind=wx.ITEM_NORMAL, text=_('Close Tab') + '\tCTRL+W')
         AppendMenu(parent, help='', id=wx.ID_CLOSE_ALL,
-                   kind=wx.ITEM_NORMAL, text=_(u'Close Project') + '\tCTRL+SHIFT+W')
+                   kind=wx.ITEM_NORMAL, text=_('Close Project') + '\tCTRL+SHIFT+W')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_PAGE_SETUP,
-                   kind=wx.ITEM_NORMAL, text=_(u'Page Setup') + '\tCTRL+ALT+P')
+                   kind=wx.ITEM_NORMAL, text=_('Page Setup') + '\tCTRL+ALT+P')
         AppendMenu(parent, help='', id=wx.ID_PREVIEW,
-                   kind=wx.ITEM_NORMAL, text=_(u'Preview') + '\tCTRL+SHIFT+P')
+                   kind=wx.ITEM_NORMAL, text=_('Preview') + '\tCTRL+SHIFT+P')
         AppendMenu(parent, help='', id=wx.ID_PRINT,
-                   kind=wx.ITEM_NORMAL, text=_(u'Print') + '\tCTRL+P')
+                   kind=wx.ITEM_NORMAL, text=_('Print') + '\tCTRL+P')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_EXIT,
-                   kind=wx.ITEM_NORMAL, text=_(u'Quit') + '\tCTRL+Q')
+                   kind=wx.ITEM_NORMAL, text=_('Quit') + '\tCTRL+Q')
 
         self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW)
         self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN)
@@ -303,11 +303,11 @@
         self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT)
         self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
 
-        self.AddToMenuToolBar([(wx.ID_NEW, "new", _(u'New'), None),
-                               (wx.ID_OPEN, "open", _(u'Open'), None),
-                               (wx.ID_SAVE, "save", _(u'Save'), None),
-                               (wx.ID_SAVEAS, "saveas", _(u'Save As...'), None),
-                               (wx.ID_PRINT, "print", _(u'Print'), None)])
+        self.AddToMenuToolBar([(wx.ID_NEW, "new", _('New'), None),
+                               (wx.ID_OPEN, "open", _('Open'), None),
+                               (wx.ID_SAVE, "save", _('Save'), None),
+                               (wx.ID_SAVEAS, "saveas", _('Save As...'), None),
+                               (wx.ID_PRINT, "print", _('Print'), None)])
 
     def _RecursiveAddMenuItems(self, menu, items):
         for name, text, helpstr, children in items:
@@ -327,14 +327,14 @@
         def handler(event):
             return wx.MessageBox(
                 version.GetCommunityHelpMsg(),
-                _(u'Community support'),
+                _('Community support'),
                 wx.OK | wx.ICON_INFORMATION)
 
-        item = parent.Append(wx.ID_ANY, _(u'Community support'), '')
+        item = parent.Append(wx.ID_ANY, _('Community support'), '')
         self.Bind(wx.EVT_MENU, handler, item)
 
         parent.Append(wx.MenuItem(helpString='', id=wx.ID_ABOUT,
-                      kind=wx.ITEM_NORMAL, text=_(u'About')))
+                      kind=wx.ITEM_NORMAL, text=_('About')))
         self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
 
     def _init_coll_ConnectionStatusBar_Fields(self, parent):
@@ -583,7 +583,7 @@
             elif answer == wx.ID_CANCEL:
                 return False
 
-        for idx in xrange(self.TabsOpened.GetPageCount()):
+        for idx in range(self.TabsOpened.GetPageCount()):
             window = self.TabsOpened.GetPage(idx)
             if not window.CheckSaveBeforeClosing():
                 return False
@@ -700,8 +700,8 @@
 
     def RefreshRecentProjectsMenu(self):
         try:
-            recent_projects = map(DecodeFileSystemPath,
-                                  self.GetConfigEntry("RecentProjects", []))
+            recent_projects = list(map(DecodeFileSystemPath,
+                                  self.GetConfigEntry("RecentProjects", [])))
         except Exception:
             recent_projects = []
 
@@ -711,7 +711,7 @@
 
         self.FileMenu.Enable(ID_FILEMENURECENTPROJECTS, len(recent_projects) > 0)
         for idx, projectpath in enumerate(recent_projects):
-            text = u'&%d: %s' % (idx + 1, projectpath)
+            text = '&%d: %s' % (idx + 1, projectpath)
 
             item = self.RecentProjectsMenu.Append(wx.ID_ANY, text, '')
             self.Bind(wx.EVT_MENU, self.GenerateOpenRecentProjectFunction(projectpath), item)
@@ -781,7 +781,7 @@
             else:
                 panel = None
             if panel != self.LastPanelSelected:
-                for i in xrange(self.EditMenuSize, self.EditMenu.GetMenuItemCount()):
+                for i in range(self.EditMenuSize, self.EditMenu.GetMenuItemCount()):
                     item = self.EditMenu.FindItemByPosition(self.EditMenuSize)
                     if item is not None:
                         if item.IsSeparator():
@@ -799,7 +799,7 @@
             if panel is not None:
                 panel.RefreshConfNodeMenu(self.EditMenu)
         else:
-            for i in xrange(self.EditMenuSize, self.EditMenu.GetMenuItemCount()):
+            for i in range(self.EditMenuSize, self.EditMenu.GetMenuItemCount()):
                 item = self.EditMenu.FindItemByPosition(i)
                 if item is not None:
                     if item.IsSeparator():
@@ -827,7 +827,7 @@
         return cPickle.loads(str(self.Config.Read(entry_name, cPickle.dumps(default))))
 
     def ResetConnectionStatusBar(self):
-        for field in xrange(self.ConnectionStatusBar.GetFieldsCount()):
+        for field in range(self.ConnectionStatusBar.GetFieldsCount()):
             self.ConnectionStatusBar.SetStatusText('', field)
 
     def ResetView(self):
@@ -842,8 +842,8 @@
 
     def RefreshConfigRecentProjects(self, projectpath, err=False):
         try:
-            recent_projects = map(DecodeFileSystemPath,
-                                  self.GetConfigEntry("RecentProjects", []))
+            recent_projects = list(map(DecodeFileSystemPath,
+                                  self.GetConfigEntry("RecentProjects", [])))
         except Exception:
             recent_projects = []
         if projectpath in recent_projects:
@@ -851,7 +851,7 @@
         if not err:
             recent_projects.insert(0, projectpath)
         self.Config.Write("RecentProjects", cPickle.dumps(
-            map(EncodeFileSystemPath, recent_projects[:MAX_RECENT_PROJECTS])))
+            list(map(EncodeFileSystemPath, recent_projects[:MAX_RECENT_PROJECTS]))))
         self.Config.Flush()
 
     def ResetPerspective(self):
--- a/Beremiz_service.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/Beremiz_service.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import sys
 import getopt
@@ -521,7 +521,7 @@
 # Load extensions
 for extention_file, extension_folder in extensions:
     sys.path.append(extension_folder)
-    execfile(os.path.join(extension_folder, extention_file), locals())
+    exec(compile(open(os.path.join(extension_folder, extention_file), "rb").read(), os.path.join(extension_folder, extention_file), 'exec'), locals())
 
 # Service name is used as an ID for stunnel's PSK
 # Some extension may set 'servicename' to a computed ID or Serial Number
--- a/CLIController.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/CLIController.py	Fri Oct 28 12:39:15 2022 +0800
@@ -117,7 +117,7 @@
         new_messages = []
         if connector:
             for level, count, prev in zip(
-                xrange(LogLevelsCount), log_count, self.previous_log_count):
+                range(LogLevelsCount), log_count, self.previous_log_count):
                 if count is not None and prev != count:
                     if prev is None:
                         dump_end = max(-1, count - 10)
--- a/CodeFileTreeNode.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/CodeFileTreeNode.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import re
 import traceback
--- a/ConfigTreeNode.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/ConfigTreeNode.py	Fri Oct 28 12:39:15 2022 +0800
@@ -31,7 +31,7 @@
 - ... TODO : document
 """
 
-from __future__ import absolute_import
+
 import os
 import traceback
 import types
@@ -319,7 +319,7 @@
         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
 
     def IterChildren(self):
-        for _CTNType, Children in self.Children.items():
+        for _CTNType, Children in list(self.Children.items()):
             for CTNInstance in Children:
                 yield CTNInstance
 
@@ -328,7 +328,7 @@
         ordered = [(chld.BaseParams.getIEC_Channel(), chld) for chld in self.IterChildren()]
         if ordered:
             ordered.sort()
-            return zip(*ordered)[1]
+            return list(zip(*ordered))[1]
         else:
             return []
 
@@ -543,8 +543,8 @@
         """
         # reorganize self.CTNChildrenTypes tuples from (name, CTNClass, Help)
         # to ( name, (CTNClass, Help)), an make a dict
-        transpose = zip(*self.CTNChildrenTypes)
-        CTNChildrenTypes = dict(zip(transpose[0], zip(transpose[1], transpose[2])))
+        transpose = list(zip(*self.CTNChildrenTypes))
+        CTNChildrenTypes = dict(list(zip(transpose[0], list(zip(transpose[1], transpose[2])))))
         # Check that adding this confnode is allowed
         try:
             CTNClass, CTNHelp = CTNChildrenTypes[CTNType]
@@ -632,7 +632,7 @@
     def LoadXMLParams(self, CTNName=None):
         methode_name = os.path.join(self.CTNPath(CTNName), "methods.py")
         if os.path.isfile(methode_name):
-            execfile(methode_name)
+            exec(compile(open(methode_name, "rb").read(), methode_name, 'exec'))
 
         ConfNodeName = CTNName if CTNName is not None else self.CTNName()
 
--- a/IDEFrame.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/IDEFrame.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,8 +22,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import sys
 import base64
 from future.builtins import \
@@ -121,7 +121,7 @@
 [
     TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
     POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
-] = range(10)
+] = list(range(10))
 
 
 def GetShortcutKeyCallbackFunction(viewer_function):
@@ -343,59 +343,59 @@
         }
 
     def _init_coll_MenuBar_Menus(self, parent):
-        parent.Append(menu=self.FileMenu, title=_(u'&File'))
-        parent.Append(menu=self.EditMenu, title=_(u'&Edit'))
-        parent.Append(menu=self.DisplayMenu, title=_(u'&Display'))
-        parent.Append(menu=self.HelpMenu, title=_(u'&Help'))
+        parent.Append(menu=self.FileMenu, title=_('&File'))
+        parent.Append(menu=self.EditMenu, title=_('&Edit'))
+        parent.Append(menu=self.DisplayMenu, title=_('&Display'))
+        parent.Append(menu=self.HelpMenu, title=_('&Help'))
 
     def _init_coll_FileMenu_Items(self, parent):
         pass
 
     def _init_coll_AddMenu_Items(self, parent, add_config=True):
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE,
-                   kind=wx.ITEM_NORMAL, text=_(u'&Data Type'))
+                   kind=wx.ITEM_NORMAL, text=_('&Data Type'))
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION,
-                   kind=wx.ITEM_NORMAL, text=_(u'&Function'))
+                   kind=wx.ITEM_NORMAL, text=_('&Function'))
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK,
-                   kind=wx.ITEM_NORMAL, text=_(u'Function &Block'))
+                   kind=wx.ITEM_NORMAL, text=_('Function &Block'))
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDPROGRAM,
-                   kind=wx.ITEM_NORMAL, text=_(u'&Program'))
+                   kind=wx.ITEM_NORMAL, text=_('&Program'))
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDRESOURCE,
-                   kind=wx.ITEM_NORMAL, text=_(u'&Resource'))
+                   kind=wx.ITEM_NORMAL, text=_('&Resource'))
         if add_config:
             AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION,
-                       kind=wx.ITEM_NORMAL, text=_(u'&Configuration'))
+                       kind=wx.ITEM_NORMAL, text=_('&Configuration'))
 
     def _init_coll_EditMenu_Items(self, parent):
         AppendMenu(parent, help='', id=wx.ID_UNDO,
-                   kind=wx.ITEM_NORMAL, text=_(u'Undo') + '\tCTRL+Z')
+                   kind=wx.ITEM_NORMAL, text=_('Undo') + '\tCTRL+Z')
         AppendMenu(parent, help='', id=wx.ID_REDO,
-                   kind=wx.ITEM_NORMAL, text=_(u'Redo') + '\tCTRL+Y')
+                   kind=wx.ITEM_NORMAL, text=_('Redo') + '\tCTRL+Y')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_CUT,
-                   kind=wx.ITEM_NORMAL, text=_(u'Cut') + '\tCTRL+X')
+                   kind=wx.ITEM_NORMAL, text=_('Cut') + '\tCTRL+X')
         AppendMenu(parent, help='', id=wx.ID_COPY,
-                   kind=wx.ITEM_NORMAL, text=_(u'Copy') + '\tCTRL+C')
+                   kind=wx.ITEM_NORMAL, text=_('Copy') + '\tCTRL+C')
         AppendMenu(parent, help='', id=wx.ID_PASTE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Paste') + '\tCTRL+V')
+                   kind=wx.ITEM_NORMAL, text=_('Paste') + '\tCTRL+V')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_FIND,
-                   kind=wx.ITEM_NORMAL, text=_(u'Find') + '\tCTRL+F')
+                   kind=wx.ITEM_NORMAL, text=_('Find') + '\tCTRL+F')
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDNEXT,
-                   kind=wx.ITEM_NORMAL, text=_(u'Find Next') + '\tCTRL+K')
+                   kind=wx.ITEM_NORMAL, text=_('Find Next') + '\tCTRL+K')
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
-                   kind=wx.ITEM_NORMAL, text=_(u'Find Previous') + '\tCTRL+SHIFT+K')
+                   kind=wx.ITEM_NORMAL, text=_('Find Previous') + '\tCTRL+SHIFT+K')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT,
-                   kind=wx.ITEM_NORMAL, text=_(u'Search in Project') + '\tCTRL+SHIFT+F')
+                   kind=wx.ITEM_NORMAL, text=_('Search in Project') + '\tCTRL+SHIFT+F')
         parent.AppendSeparator()
         add_menu = wx.Menu(title='')
         self._init_coll_AddMenu_Items(add_menu)
-        parent.Append(wx.ID_ADD, _(u"&Add Element"), add_menu)
+        parent.Append(wx.ID_ADD, _("&Add Element"), add_menu)
         AppendMenu(parent, help='', id=wx.ID_SELECTALL,
-                   kind=wx.ITEM_NORMAL, text=_(u'Select All') + '\tCTRL+A')
+                   kind=wx.ITEM_NORMAL, text=_('Select All') + '\tCTRL+A')
         AppendMenu(parent, help='', id=wx.ID_DELETE,
-                   kind=wx.ITEM_NORMAL, text=_(u'&Delete'))
+                   kind=wx.ITEM_NORMAL, text=_('&Delete'))
         self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
         self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
         # self.Bind(wx.EVT_MENU, self.OnEnableUndoRedoMenu, id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO)
@@ -424,22 +424,22 @@
         self.Bind(wx.EVT_MENU, self.OnSelectAllMenu, id=wx.ID_SELECTALL)
         self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE)
 
-        self.AddToMenuToolBar([(wx.ID_UNDO, "undo", _(u'Undo'), None),
-                               (wx.ID_REDO, "redo", _(u'Redo'), None),
+        self.AddToMenuToolBar([(wx.ID_UNDO, "undo", _('Undo'), None),
+                               (wx.ID_REDO, "redo", _('Redo'), None),
                                None,
-                               (wx.ID_CUT, "cut", _(u'Cut'), None),
-                               (wx.ID_COPY, "copy", _(u'Copy'), None),
-                               (wx.ID_PASTE, "paste", _(u'Paste'), None),
+                               (wx.ID_CUT, "cut", _('Cut'), None),
+                               (wx.ID_COPY, "copy", _('Copy'), None),
+                               (wx.ID_PASTE, "paste", _('Paste'), None),
                                None,
-                               (ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, "find", _(u'Search in Project'), None),
-                               (ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN, "fullscreen", _(u'Toggle fullscreen mode'), None)])
+                               (ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, "find", _('Search in Project'), None),
+                               (ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN, "fullscreen", _('Toggle fullscreen mode'), None)])
 
     def _init_coll_DisplayMenu_Items(self, parent):
         AppendMenu(parent, help='', id=wx.ID_REFRESH,
-                   kind=wx.ITEM_NORMAL, text=_(u'Refresh') + '\tCTRL+R')
+                   kind=wx.ITEM_NORMAL, text=_('Refresh') + '\tCTRL+R')
         if self.EnableDebug:
             AppendMenu(parent, help='', id=wx.ID_CLEAR,
-                       kind=wx.ITEM_NORMAL, text=_(u'Clear Errors') + '\tCTRL+K')
+                       kind=wx.ITEM_NORMAL, text=_('Clear Errors') + '\tCTRL+K')
         parent.AppendSeparator()
         zoommenu = wx.Menu(title='')
         parent.Append(wx.ID_ZOOM_FIT, _("Zoom"), zoommenu)
@@ -450,15 +450,15 @@
 
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Switch perspective') + '\tF12')
+                   kind=wx.ITEM_NORMAL, text=_('Switch perspective') + '\tF12')
         self.Bind(wx.EVT_MENU, self.SwitchPerspective, id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE)
 
         AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN,
-                   kind=wx.ITEM_NORMAL, text=_(u'Full screen') + '\tShift-F12')
+                   kind=wx.ITEM_NORMAL, text=_('Full screen') + '\tShift-F12')
         self.Bind(wx.EVT_MENU, self.SwitchFullScrMode, id=ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN)
 
         AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Reset Perspective'))
+                   kind=wx.ITEM_NORMAL, text=_('Reset Perspective'))
         self.Bind(wx.EVT_MENU, self.OnResetPerspective, id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE)
 
         self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
@@ -792,7 +792,7 @@
     # -------------------------------------------------------------------------------
 
     def GetTabInfos(self, tab):
-        for page_name, (page_ref, _page_title) in self.MainTabs.iteritems():
+        for page_name, (page_ref, _page_title) in self.MainTabs.items():
             if page_ref == tab:
                 return ("main", page_name)
         return None
@@ -805,7 +805,7 @@
                     pos = child.GetPosition()
                     tab = {"pos": (pos.x, pos.y), "pages": []}
                     tab_size = child.GetSize()
-                    for page_idx in xrange(child.GetPageCount()):
+                    for page_idx in range(child.GetPageCount()):
                         page = child.GetWindowFromIdx(page_idx)
                         if "size" not in tab:
                             tab["size"] = (tab_size[0], tab_size[1] + page.GetSize()[1])
@@ -871,7 +871,7 @@
             self.AUIManager.LoadPerspective(self.DefaultPerspective["perspective"])
 
             for notebook in [self.LeftNoteBook, self.BottomNoteBook, self.RightNoteBook]:
-                for dummy in xrange(notebook.GetPageCount()):
+                for dummy in range(notebook.GetPageCount()):
                     notebook.RemovePage(0)
 
             notebooks = self.DefaultPerspective["notebooks"]
@@ -982,7 +982,7 @@
         return self.DrawingMode
 
     def RefreshScaling(self):
-        for i in xrange(self.TabsOpened.GetPageCount()):
+        for i in range(self.TabsOpened.GetPageCount()):
             editor = self.TabsOpened.GetPage(i)
             editor.RefreshScaling()
 
@@ -1014,7 +1014,7 @@
         self.RefreshTabCtrlEvent()
 
     def DeletePage(self, window):
-        for idx in xrange(self.TabsOpened.GetPageCount()):
+        for idx in range(self.TabsOpened.GetPageCount()):
             if self.TabsOpened.GetPage(idx) == window:
                 self.TabsOpened.DeletePage(idx)
                 self.RefreshTabCtrlEvent()
@@ -1024,7 +1024,7 @@
         """Function that fix difference in deleting all tabs between
         wx.Notebook and wx.aui.AUINotebook.
         """
-        for dummy in xrange(self.TabsOpened.GetPageCount()):
+        for dummy in range(self.TabsOpened.GetPageCount()):
             self.TabsOpened.DeletePage(0)
         self.RefreshTabCtrlEvent()
 
@@ -1065,7 +1065,7 @@
             elif answer == wx.ID_CANCEL:
                 return False
 
-        for idx in xrange(self.TabsOpened.GetPageCount()):
+        for idx in range(self.TabsOpened.GetPageCount()):
             window = self.TabsOpened.GetPage(idx)
             if not window.CheckSaveBeforeClosing():
                 return False
@@ -1114,7 +1114,7 @@
             window = self.TabsOpened.GetPage(selected)
             data = wx.PrintDialogData(self.PrintData)
             properties = self.Controler.GetProjectProperties(window.IsDebugging())
-            page_size = map(int, properties["pageSize"])
+            page_size = list(map(int, properties["pageSize"]))
             margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
             printout = GraphicPrintout(window, page_size, margins, True)
             printout2 = GraphicPrintout(window, page_size, margins, True)
@@ -1138,7 +1138,7 @@
             dialog_data = wx.PrintDialogData(self.PrintData)
             dialog_data.SetToPage(1)
             properties = self.Controler.GetProjectProperties(window.IsDebugging())
-            page_size = map(int, properties["pageSize"])
+            page_size = list(map(int, properties["pageSize"]))
             margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
             printer = wx.Printer(dialog_data)
             printout = GraphicPrintout(window, page_size, margins)
@@ -1227,7 +1227,7 @@
             self.EditMenu.Enable(wx.ID_DELETE, False)
 
     def CloseTabsWithoutModel(self, refresh=True):
-        idxs = range(self.TabsOpened.GetPageCount())
+        idxs = list(range(self.TabsOpened.GetPageCount()))
         idxs.reverse()
         for idx in idxs:
             window = self.TabsOpened.GetPage(idx)
@@ -1475,19 +1475,19 @@
             self._Refresh(FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR)
 
     def RefreshEditorNames(self, old_tagname, new_tagname):
-        for i in xrange(self.TabsOpened.GetPageCount()):
+        for i in range(self.TabsOpened.GetPageCount()):
             editor = self.TabsOpened.GetPage(i)
             if editor.GetTagName() == old_tagname:
                 editor.SetTagName(new_tagname)
 
     def IsOpened(self, tagname):
-        for idx in xrange(self.TabsOpened.GetPageCount()):
+        for idx in range(self.TabsOpened.GetPageCount()):
             if self.TabsOpened.GetPage(idx).IsViewing(tagname):
                 return idx
         return None
 
     def RefreshPageTitles(self):
-        for idx in xrange(self.TabsOpened.GetPageCount()):
+        for idx in range(self.TabsOpened.GetPageCount()):
             window = self.TabsOpened.GetPage(idx)
             icon = window.GetIcon()
             if icon is not None:
@@ -1601,7 +1601,7 @@
             if root is not None and root.IsOk():
                 words = tagname.split("::")
                 result = self.RecursiveProjectTreeItemSelection(
-                    root, zip(words[1:], self.TagNamePartsItemTypes.get(words[0], [])))
+                    root, list(zip(words[1:], self.TagNamePartsItemTypes.get(words[0], []))))
         return result
 
     def RecursiveProjectTreeItemSelection(self, root, items):
@@ -1890,7 +1890,7 @@
                 if old_selected != openedidx:
                     if old_selected >= 0:
                         self.TabsOpened.GetPage(old_selected).ResetBuffer()
-                for i in xrange(self.TabsOpened.GetPageCount()):
+                for i in range(self.TabsOpened.GetPageCount()):
                     window = self.TabsOpened.GetPage(i)
                     if window == new_window:
                         self.TabsOpened.SetSelection(i)
@@ -2083,7 +2083,7 @@
 
     def CloseObsoleteDebugTabs(self):
         if self.EnableDebug:
-            idxs = range(self.TabsOpened.GetPageCount())
+            idxs = list(range(self.TabsOpened.GetPageCount()))
             idxs.reverse()
             for idx in idxs:
                 editor = self.TabsOpened.GetPage(idx)
@@ -2572,9 +2572,9 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            self.Highlights = dict([(name, highlight) for name, highlight in self.Highlights.iteritems() if highlight != highlight_type])
+            self.Highlights = dict([(name, highlight) for name, highlight in self.Highlights.items() if highlight != highlight_type])
         self.RefreshProjectTree()
-        for i in xrange(self.TabsOpened.GetPageCount()):
+        for i in range(self.TabsOpened.GetPageCount()):
             viewer = self.TabsOpened.GetPage(i)
             viewer.ClearHighlights(highlight_type)
 
--- a/NativeLib.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/NativeLib.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import util.paths as paths
 from POULibrary import SimplePOULibraryFactory
 
--- a/PLCControler.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/PLCControler.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from copy import deepcopy
 import os
 import re
@@ -74,7 +74,7 @@
             self.MinIndex = 0
             self.MaxIndex = 0
         # Initialising buffer with currentstate at the first place
-        for i in xrange(UNDO_BUFFER_LENGTH):
+        for i in range(UNDO_BUFFER_LENGTH):
             if i == 0:
                 self.Buffer.append(currentstate)
             else:
@@ -1184,7 +1184,7 @@
         for _sectioname, blocktype in self.TotalTypesDict.get(typename, []):
             if inputs is not None and inputs != "undefined":
                 block_inputs = tuple([var_type for _name, var_type, _modifier in blocktype["inputs"]])
-                if reduce(lambda x, y: x and y, map(lambda x: x[0] == "ANY" or self.IsOfType(*x), zip(inputs, block_inputs)), True):
+                if reduce(lambda x, y: x and y, [x[0] == "ANY" or self.IsOfType(*x) for x in zip(inputs, block_inputs)], True):
                     return blocktype
             else:
                 if result_blocktype:
@@ -1247,7 +1247,7 @@
         if project is not None and words[0] in ["P", "T", "A"]:
             name = words[1]
         blocktypes = []
-        for blocks in self.TotalTypesDict.itervalues():
+        for blocks in self.TotalTypesDict.values():
             for _sectioname, block in blocks:
                 if block["type"] == "functionBlock":
                     blocktypes.append(block["name"])
@@ -1302,7 +1302,7 @@
             result = project.getpou(typename)
             if result is not None:
                 return result
-        for standardlibrary in StdBlckLibs.values():
+        for standardlibrary in list(StdBlckLibs.values()):
             result = standardlibrary.getpou(typename)
             if result is not None:
                 return result
@@ -1455,7 +1455,7 @@
 
     # Return Subrange types
     def GetSubrangeBaseTypes(self, exclude, debug=False):
-        subrange_basetypes = DataTypeRange.keys()
+        subrange_basetypes = list(DataTypeRange.keys())
         project = self.GetProject(debug)
         if project is not None:
             subrange_basetypes.extend(
@@ -1970,9 +1970,9 @@
                 new_pos[0] -= width // 2
                 new_pos[1] -= height // 2
             else:
-                new_pos = map(lambda x: x + 30, new_pos)
+                new_pos = [x + 30 for x in new_pos]
             if scaling[0] != 0 and scaling[1] != 0:
-                min_pos = map(lambda x: 30 / x, scaling)
+                min_pos = [30 / x for x in scaling]
                 minx = round(min_pos[0])
                 if int(min_pos[0]) == round(min_pos[0]):
                     minx += 1
@@ -2118,7 +2118,7 @@
                     self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name)
             elif new_name != old_name:
                 self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name)
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "name":
                     if value != "":
                         block.setinstanceName(value)
@@ -2179,7 +2179,7 @@
             variable = element.getinstance(id)
             if variable is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "name":
                     variable.setexpression(value)
                 elif param == "executionOrder" and variable.getexecutionOrderId() != value:
@@ -2232,7 +2232,7 @@
             connection = element.getinstance(id)
             if connection is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "name":
                     connection.setname(value)
                 elif param == "height":
@@ -2264,7 +2264,7 @@
         element = self.GetEditedElement(tagname)
         if element is not None:
             comment = element.getinstance(id)
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "content":
                     comment.setcontentText(value)
                 elif param == "height":
@@ -2291,7 +2291,7 @@
             powerrail = element.getinstance(id)
             if powerrail is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "height":
                     powerrail.setheight(value)
                 elif param == "width":
@@ -2330,7 +2330,7 @@
             contact = element.getinstance(id)
             if contact is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "name":
                     contact.setvariable(value)
                 elif param == "type":
@@ -2373,7 +2373,7 @@
             coil = element.getinstance(id)
             if coil is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "name":
                     coil.setvariable(value)
                 elif param == "type":
@@ -2419,7 +2419,7 @@
             step = element.getinstance(id)
             if step is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "name":
                     step.setname(value)
                 elif param == "initial":
@@ -2469,7 +2469,7 @@
             transition = element.getinstance(id)
             if transition is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "type" and value != "connection":
                     transition.setconditionContent(value, infos["condition"])
                 elif param == "height":
@@ -2529,7 +2529,7 @@
             divergence = element.getinstance(id)
             if divergence is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "height":
                     divergence.setheight(value)
                 elif param == "width":
@@ -2580,7 +2580,7 @@
             jump = element.getinstance(id)
             if jump is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "target":
                     jump.settargetName(value)
                 elif param == "height":
@@ -2610,7 +2610,7 @@
             actionBlock = element.getinstance(id)
             if actionBlock is None:
                 return
-            for param, value in infos.items():
+            for param, value in list(infos.items()):
                 if param == "actions":
                     actionBlock.setactions(value)
                 elif param == "height":
--- a/PLCGenerator.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/PLCGenerator.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import re
 from functools import reduce
 from six.moves import xrange
@@ -65,7 +65,7 @@
             while lines[line_num][spaces] == " ":
                 spaces += 1
             indent = ""
-            for dummy in xrange(spaces, nb_spaces):
+            for dummy in range(spaces, nb_spaces):
                 indent += " "
             for line in lines:
                 if line != "":
@@ -264,7 +264,7 @@
 
     # Generate a POU defined and used in text
     def GeneratePouProgramInText(self, text):
-        for pou_name in self.PouComputed.keys():
+        for pou_name in list(self.PouComputed.keys()):
             model = re.compile("(?:^|[^0-9^A-Z])%s(?:$|[^0-9^A-Z])" % pou_name.upper())
             if model.search(text) is not None:
                 self.GeneratePouProgram(pou_name)
@@ -472,12 +472,12 @@
         if len(self.DatatypeComputed) > 0:
             self.Program += [("TYPE\n", ())]
             # Generate every data types defined
-            for datatype_name in self.DatatypeComputed.keys():
+            for datatype_name in list(self.DatatypeComputed.keys()):
                 log("Generate Data Type %s"%datatype_name)
                 self.GenerateDataType(datatype_name)
             self.Program += [("END_TYPE\n\n", ())]
         # Generate every POUs defined
-        for pou_name in self.PouComputed.keys():
+        for pou_name in list(self.PouComputed.keys()):
             log("Generate POU %s"%pou_name)
             self.GeneratePouProgram(pou_name)
         if noconfig:
@@ -895,7 +895,7 @@
                             if connected is not None and connected not in self.ConnectionTypes:
                                 for connection in self.ExtractRelatedConnections(connected):
                                     self.ConnectionTypes[connection] = itype
-        for var_type, connections in undefined.items():
+        for var_type, connections in list(undefined.items()):
             related = []
             for connection in connections:
                 connection_type = self.ConnectionTypes.get(connection)
@@ -1055,7 +1055,7 @@
 
     def FactorizePaths(self, paths):
         same_paths = {}
-        uncomputed_index = range(len(paths))
+        uncomputed_index = list(range(len(paths)))
         factorized_paths = []
         for num, path in enumerate(paths):
             if isinstance(path, list):
@@ -1066,7 +1066,7 @@
             else:
                 factorized_paths.append(path)
                 uncomputed_index.remove(num)
-        for same_path, elements in same_paths.items():
+        for same_path, elements in list(same_paths.items()):
             if len(elements) > 1:
                 elements_paths = self.FactorizePaths([path for path, num in elements])
                 if len(elements_paths) > 1:
@@ -1452,7 +1452,7 @@
 
     def GenerateSFCStep(self, step, pou):
         step_name = step.getname()
-        if step_name not in self.SFCNetworks["Steps"].keys():
+        if step_name not in list(self.SFCNetworks["Steps"].keys()):
             if step.getinitialStep():
                 self.InitialSteps.append(step_name)
             step_infos = {"id":          step.getlocalId(),
@@ -1482,7 +1482,7 @@
                                 instances.extend(self.ExtractConvergenceInputs(transition, pou))
                 for instance in instances:
                     self.GenerateSFCTransition(instance, pou)
-                    if instance in self.SFCNetworks["Transitions"].keys():
+                    if instance in list(self.SFCNetworks["Transitions"].keys()):
                         target_info = (self.TagName, "transition", instance.getlocalId(), "to", step_infos["id"])
                         self.SFCNetworks["Transitions"][instance]["to"].append([(step_name, target_info)])
 
@@ -1516,7 +1516,7 @@
                             instances.extend(self.ExtractConvergenceInputs(transition, pou))
             for instance in instances:
                 self.GenerateSFCTransition(instance, pou)
-                if instance in self.SFCNetworks["Transitions"].keys():
+                if instance in list(self.SFCNetworks["Transitions"].keys()):
                     target_info = (self.TagName, "jump", jump.getlocalId(), "target")
                     self.SFCNetworks["Transitions"][instance]["to"].append([(jump_target, target_info)])
 
@@ -1530,7 +1530,7 @@
             step = body.getcontentInstance(stepLocalId)
             self.GenerateSFCStep(step, pou)
             step_name = step.getname()
-            if step_name in self.SFCNetworks["Steps"].keys():
+            if step_name in list(self.SFCNetworks["Steps"].keys()):
                 actions = actionBlock.getactions()
                 for i, action in enumerate(actions):
                     action_infos = {"id":        actionBlock.getlocalId(),
@@ -1555,7 +1555,7 @@
                     self.SFCNetworks["Steps"][step_name]["actions"].append(action_infos)
 
     def GenerateSFCAction(self, action_name, pou):
-        if action_name not in self.SFCNetworks["Actions"].keys():
+        if action_name not in list(self.SFCNetworks["Actions"].keys()):
             actionContent = pou.getaction(action_name)
             if actionContent is not None:
                 previous_tagname = self.TagName
@@ -1566,7 +1566,7 @@
                 self.TagName = previous_tagname
 
     def GenerateSFCTransition(self, transition, pou):
-        if transition not in self.SFCNetworks["Transitions"].keys():
+        if transition not in list(self.SFCNetworks["Transitions"].keys()):
             steps = []
             connections = transition.connectionPointIn.getconnections()
             if connections is not None and len(connections) == 1:
@@ -1639,12 +1639,12 @@
             for step in steps:
                 self.GenerateSFCStep(step, pou)
                 step_name = step.getname()
-                if step_name in self.SFCNetworks["Steps"].keys():
+                if step_name in list(self.SFCNetworks["Steps"].keys()):
                     transition_infos["from"].append([(step_name, (self.TagName, "transition", transition.getlocalId(), "from", step.getlocalId()))])
                     self.SFCNetworks["Steps"][step_name]["transitions"].append(transition)
 
     def ComputeSFCStep(self, step_name):
-        if step_name in self.SFCNetworks["Steps"].keys():
+        if step_name in list(self.SFCNetworks["Steps"].keys()):
             step_infos = self.SFCNetworks["Steps"].pop(step_name)
             self.Program += [(self.CurrentIndent, ())]
             if step_infos["initial"]:
@@ -1679,7 +1679,7 @@
                 self.ComputeSFCTransition(transition)
 
     def ComputeSFCAction(self, action_name):
-        if action_name in self.SFCNetworks["Actions"].keys():
+        if action_name in list(self.SFCNetworks["Actions"].keys()):
             action_content, action_info = self.SFCNetworks["Actions"].pop(action_name)
             self.Program += [("%sACTION " % self.CurrentIndent, ()),
                              (action_name, action_info),
@@ -1688,7 +1688,7 @@
             self.Program += [("%sEND_ACTION\n\n" % self.CurrentIndent, ())]
 
     def ComputeSFCTransition(self, transition):
-        if transition in self.SFCNetworks["Transitions"].keys():
+        if transition in list(self.SFCNetworks["Transitions"].keys()):
             transition_infos = self.SFCNetworks["Transitions"].pop(transition)
             self.Program += [("%sTRANSITION" % self.CurrentIndent, ())]
             if transition_infos["priority"] is not None:
--- a/PLCOpenEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/PLCOpenEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import sys
 import getopt
@@ -74,35 +74,35 @@
 
     def _init_coll_FileMenu_Items(self, parent):
         AppendMenu(parent, help='', id=wx.ID_NEW,
-                   kind=wx.ITEM_NORMAL, text=_(u'New') + '\tCTRL+N')
+                   kind=wx.ITEM_NORMAL, text=_('New') + '\tCTRL+N')
         AppendMenu(parent, help='', id=wx.ID_OPEN,
-                   kind=wx.ITEM_NORMAL, text=_(u'Open') + '\tCTRL+O')
+                   kind=wx.ITEM_NORMAL, text=_('Open') + '\tCTRL+O')
         AppendMenu(parent, help='', id=wx.ID_CLOSE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Close Tab') + '\tCTRL+W')
+                   kind=wx.ITEM_NORMAL, text=_('Close Tab') + '\tCTRL+W')
         AppendMenu(parent, help='', id=wx.ID_CLOSE_ALL,
-                   kind=wx.ITEM_NORMAL, text=_(u'Close Project') + '\tCTRL+SHIFT+W')
+                   kind=wx.ITEM_NORMAL, text=_('Close Project') + '\tCTRL+SHIFT+W')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_SAVE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Save') + '\tCTRL+S')
+                   kind=wx.ITEM_NORMAL, text=_('Save') + '\tCTRL+S')
         AppendMenu(parent, help='', id=wx.ID_SAVEAS,
-                   kind=wx.ITEM_NORMAL, text=_(u'Save As...') + '\tCTRL+SHIFT+S')
+                   kind=wx.ITEM_NORMAL, text=_('Save As...') + '\tCTRL+SHIFT+S')
         AppendMenu(parent, help='', id=ID_PLCOPENEDITORFILEMENUGENERATE,
-                   kind=wx.ITEM_NORMAL, text=_(u'Generate Program') + '\tCTRL+G')
+                   kind=wx.ITEM_NORMAL, text=_('Generate Program') + '\tCTRL+G')
         AppendMenu(parent, help='', id=ID_PLCOPENEDITORFILEMENUGENERATEAS,
-                   kind=wx.ITEM_NORMAL, text=_(u'Generate Program As...') + '\tCTRL+SHIFT+G')
+                   kind=wx.ITEM_NORMAL, text=_('Generate Program As...') + '\tCTRL+SHIFT+G')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_PAGE_SETUP,
-                   kind=wx.ITEM_NORMAL, text=_(u'Page Setup') + '\tCTRL+ALT+P')
+                   kind=wx.ITEM_NORMAL, text=_('Page Setup') + '\tCTRL+ALT+P')
         AppendMenu(parent, help='', id=wx.ID_PREVIEW,
-                   kind=wx.ITEM_NORMAL, text=_(u'Preview') + '\tCTRL+SHIFT+P')
+                   kind=wx.ITEM_NORMAL, text=_('Preview') + '\tCTRL+SHIFT+P')
         AppendMenu(parent, help='', id=wx.ID_PRINT,
-                   kind=wx.ITEM_NORMAL, text=_(u'Print') + '\tCTRL+P')
+                   kind=wx.ITEM_NORMAL, text=_('Print') + '\tCTRL+P')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_PROPERTIES,
-                   kind=wx.ITEM_NORMAL, text=_(u'&Properties'))
+                   kind=wx.ITEM_NORMAL, text=_('&Properties'))
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=wx.ID_EXIT,
-                   kind=wx.ITEM_NORMAL, text=_(u'Quit') + '\tCTRL+Q')
+                   kind=wx.ITEM_NORMAL, text=_('Quit') + '\tCTRL+Q')
 
         self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW)
         self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN)
@@ -120,16 +120,16 @@
         self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, id=wx.ID_PROPERTIES)
         self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
 
-        self.AddToMenuToolBar([(wx.ID_NEW, "new", _(u'New'), None),
-                               (wx.ID_OPEN, "open", _(u'Open'), None),
-                               (wx.ID_SAVE, "save", _(u'Save'), None),
-                               (wx.ID_SAVEAS, "saveas", _(u'Save As...'), None),
-                               (wx.ID_PRINT, "print", _(u'Print'), None),
-                               (ID_PLCOPENEDITORFILEMENUGENERATE, "Build", _(u'Generate Program'), None)])
+        self.AddToMenuToolBar([(wx.ID_NEW, "new", _('New'), None),
+                               (wx.ID_OPEN, "open", _('Open'), None),
+                               (wx.ID_SAVE, "save", _('Save'), None),
+                               (wx.ID_SAVEAS, "saveas", _('Save As...'), None),
+                               (wx.ID_PRINT, "print", _('Print'), None),
+                               (ID_PLCOPENEDITORFILEMENUGENERATE, "Build", _('Generate Program'), None)])
 
     def _init_coll_HelpMenu_Items(self, parent):
         AppendMenu(parent, help='', id=wx.ID_HELP,
-                   kind=wx.ITEM_NORMAL, text=_(u'PLCOpenEditor') + '\tF1')
+                   kind=wx.ITEM_NORMAL, text=_('PLCOpenEditor') + '\tF1')
         # AppendMenu(parent, help='', id=wx.ID_HELP_CONTENTS,
         #      kind=wx.ITEM_NORMAL, text=u'PLCOpen\tF2')
         # AppendMenu(parent, help='', id=wx.ID_HELP_CONTEXT,
@@ -138,14 +138,14 @@
         def handler(event):
             return wx.MessageBox(
                 version.GetCommunityHelpMsg(),
-                _(u'Community support'),
+                _('Community support'),
                 wx.OK | wx.ICON_INFORMATION)
 
-        menu_entry = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text=_(u'Community support'))
+        menu_entry = parent.Append(help='', id=wx.ID_ANY, kind=wx.ITEM_NORMAL, text=_('Community support'))
         self.Bind(wx.EVT_MENU, handler, menu_entry)
 
         AppendMenu(parent, help='', id=wx.ID_ABOUT,
-                   kind=wx.ITEM_NORMAL, text=_(u'About'))
+                   kind=wx.ITEM_NORMAL, text=_('About'))
         self.Bind(wx.EVT_MENU, self.OnPLCOpenEditorMenu, id=wx.ID_HELP)
         # self.Bind(wx.EVT_MENU, self.OnPLCOpenMenu, id=wx.ID_HELP_CONTENTS)
         self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
--- a/POULibrary.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/POULibrary.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from weakref import ref
 
 # Exception type for problems that user has to take action in order to fix
--- a/PSKManagement.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/PSKManagement.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import os
 import time
 import json
@@ -11,8 +11,8 @@
 
 # PSK Management Data model :
 # [[ID,Desc, LastKnownURI, LastConnect]]
-COL_ID, COL_URI, COL_DESC, COL_LAST = range(4)
-REPLACE, REPLACE_ALL, KEEP, KEEP_ALL, CANCEL = range(5)
+COL_ID, COL_URI, COL_DESC, COL_LAST = list(range(4))
+REPLACE, REPLACE_ALL, KEEP, KEEP_ALL, CANCEL = list(range(5))
 
 
 def _pskpath(project_path):
--- a/ProjectController.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/ProjectController.py	Fri Oct 28 12:39:15 2022 +0800
@@ -28,7 +28,7 @@
 """
 
 
-from __future__ import absolute_import
+
 import os
 import traceback
 import time
@@ -40,7 +40,7 @@
 from datetime import datetime
 from weakref import WeakKeyDictionary
 from functools import reduce
-from itertools import izip
+
 from distutils.dir_util import copy_tree
 from six.moves import xrange
 
@@ -634,7 +634,7 @@
             LocatedCCodeAndFlags.append(res[:2])
             if len(res) > 2:
                 Extras.extend(res[2:])
-        return map(list, zip(*LocatedCCodeAndFlags)) + [tuple(Extras)]
+        return list(map(list, list(zip(*LocatedCCodeAndFlags)))) + [tuple(Extras)]
 
     # Update PLCOpenEditor ConfNode Block types from loaded confnodes
     def RefreshConfNodesBlockLists(self):
@@ -888,15 +888,13 @@
                 _("Error : At least one configuration and one resource must be declared in PLC !\n"))
             return False
         # transform those base names to full names with path
-        C_files = map(
-            lambda filename: os.path.join(buildpath, filename), C_files)
+        C_files = [os.path.join(buildpath, filename) for filename in C_files]
 
         # prepend beremiz include to configuration header
         H_files = [fname for fname in result.splitlines() if fname[
             -2:] == ".h" or fname[-2:] == ".H"]
         H_files.remove("LOCATED_VARIABLES.h")
-        H_files = map(
-            lambda filename: os.path.join(buildpath, filename), H_files)
+        H_files = [os.path.join(buildpath, filename) for filename in H_files]
         for H_file in H_files:
             with open(H_file, 'r') as original:
                 data = original.read()
@@ -995,7 +993,7 @@
                 for line in ListGroup[0]:
                     # Split and Maps each field to dictionnary entries
                     attrs = dict(
-                        zip(ProgramsListAttributeName, line.strip().split(';')))
+                        list(zip(ProgramsListAttributeName, line.strip().split(';'))))
                     # Truncate "C_path" to remove conf an resources names
                     attrs["C_path"] = '__'.join(
                         attrs["C_path"].split(".", 2)[1:])
@@ -1008,7 +1006,7 @@
                 for line in ListGroup[1]:
                     # Split and Maps each field to dictionnary entries
                     attrs = dict(
-                        zip(VariablesListAttributeName, line.strip().split(';')))
+                        list(zip(VariablesListAttributeName, line.strip().split(';'))))
                     # Truncate "C_path" to remove conf an resources names
                     parts = attrs["C_path"].split(".", 2)
                     if len(parts) > 2:
@@ -1098,9 +1096,8 @@
         """
         # filter location that are related to code that will be called
         # in retreive, publish, init, cleanup
-        locstrs = map(lambda x: "_".join(map(str, x)),
-                      [loc for loc, _Cfiles, DoCalls in
-                       self.LocationCFilesAndCFLAGS if loc and DoCalls])
+        locstrs = ["_".join(map(str, x)) for x in [loc for loc, _Cfiles, DoCalls in
+                       self.LocationCFilesAndCFLAGS if loc and DoCalls]]
 
         # Generate main, based on template
         if not self.BeremizRoot.getDisable_Extensions():
@@ -1113,7 +1110,7 @@
                 "retrieve_calls": "\n    ".join([
                     "__retrieve_%s();" % locstr for locstr in locstrs]),
                 "publish_calls": "\n    ".join([  # Call publish in reverse order
-                    "__publish_%s();" % locstrs[i - 1] for i in xrange(len(locstrs), 0, -1)]),
+                    "__publish_%s();" % locstrs[i - 1] for i in range(len(locstrs), 0, -1)]),
                 "init_calls": "\n    ".join([
                     "init_level=%d; " % (i + 1) +
                     "if((res = __init_%s(argc,argv))){" % locstr +
@@ -1121,7 +1118,7 @@
                     "return res;}" for i, locstr in enumerate(locstrs)]),
                 "cleanup_calls": "\n    ".join([
                     "if(init_level >= %d) " % i +
-                    "__cleanup_%s();" % locstrs[i - 1] for i in xrange(len(locstrs), 0, -1)])
+                    "__cleanup_%s();" % locstrs[i - 1] for i in range(len(locstrs), 0, -1)])
             }
         else:
             plc_main_code = targets.GetCode("plc_main_head.c") % {
@@ -1395,9 +1392,9 @@
 
                     if editor_name == "":
                         if len(editors) == 1:
-                            editor_name = editors.keys()[0]
+                            editor_name = list(editors.keys())[0]
                         elif len(editors) > 0:
-                            names = editors.keys()
+                            names = list(editors.keys())
                             dialog = wx.SingleChoiceDialog(
                                 self.AppFrame,
                                 _("Select an editor:"),
@@ -1434,7 +1431,7 @@
             self._IECRawCodeView = None
         if self._ProjectFilesView == view:
             self._ProjectFilesView = None
-        if view in self._FileEditors.values():
+        if view in list(self._FileEditors.values()):
             self._FileEditors.pop(view.GetFilePath())
 
     def _Clean(self):
@@ -1506,7 +1503,7 @@
             allmethods = self.DefaultMethods.copy()
             allmethods.update(
                 self.MethodsFromStatus.get(status, {}))
-            for method, active in allmethods.items():
+            for method, active in list(allmethods.items()):
                 self.ShowMethod(method, active)
             self.previous_plcstate = status
             if self.AppFrame is not None:
@@ -1552,7 +1549,7 @@
                         debug_vars = UnpackDebugBuffer(
                             debug_buff, self.TracedIECTypes)
                         if debug_vars is not None:
-                            for IECPath, values_buffer, value in izip(
+                            for IECPath, values_buffer, value in zip(
                                     self.TracedIECPath,
                                     self.DebugValuesBuffers,
                                     debug_vars):
@@ -1578,7 +1575,7 @@
 
 
         buffers, self.DebugValuesBuffers = (self.DebugValuesBuffers,
-                                            [list() for dummy in xrange(len(self.TracedIECPath))])
+                                            [list() for dummy in range(len(self.TracedIECPath))])
 
         ticks, self.DebugTicks = self.DebugTicks, []
 
@@ -1603,7 +1600,7 @@
         self.TracedIECTypes = []
         if self._connector is not None and self.debug_status != PlcStatus.Broken:
             IECPathsToPop = []
-            for IECPath, data_tuple in self.IECdebug_datas.iteritems():
+            for IECPath, data_tuple in self.IECdebug_datas.items():
                 WeakCallableDict, _data_log, _status, fvalue, _buffer_list = data_tuple
                 if len(WeakCallableDict) == 0:
                     # Callable Dict is empty.
@@ -1627,10 +1624,10 @@
 
             if Idxs:
                 Idxs.sort()
-                IdxsT = zip(*Idxs)
+                IdxsT = list(zip(*Idxs))
                 self.TracedIECPath = IdxsT[3]
                 self.TracedIECTypes = IdxsT[1]
-                res = self._connector.SetTraceVariablesList(zip(*IdxsT[0:3]))
+                res = self._connector.SetTraceVariablesList(list(zip(*IdxsT[0:3])))
                 if res is not None and res > 0:
                     self.DebugToken = res
                 else:
@@ -1695,7 +1692,7 @@
             else:
                 IECdebug_data[4] = reduce(
                     lambda x, y: x | y,
-                    IECdebug_data[0].itervalues(),
+                    iter(IECdebug_data[0].values()),
                     False)
 
         self.AppendDebugUpdate()
@@ -1732,7 +1729,7 @@
         if data_tuple is not None:
             WeakCallableDict, _data_log, _status, _fvalue, buffer_list = data_tuple
             # data_log.append((debug_tick, value))
-            for weakcallable, buffer_list in WeakCallableDict.iteritems():
+            for weakcallable, buffer_list in WeakCallableDict.items():
                 function = getattr(weakcallable, function_name, None)
                 if function is not None:
                     # FIXME: apparently, despite of weak ref objects,
--- a/XSLTransform.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/XSLTransform.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # This file is part of Beremiz.
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 from lxml import etree
 
 class XSLTransform(object):
@@ -18,7 +18,7 @@
             extensions={("beremiz", name): call for name, call in xsltext})
 
     def transform(self, root, profile_run=False, **kwargs):
-        res = self.xslt(root, profile_run=profile_run, **{k: etree.XSLT.strparam(v) for k, v in kwargs.iteritems()})
+        res = self.xslt(root, profile_run=profile_run, **{k: etree.XSLT.strparam(v) for k, v in kwargs.items()})
         # print(self.xslt.error_log)
         return res
 
--- a/bacnet/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/bacnet/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,6 +23,6 @@
 # used in safety-critical situations without a full and competent review.
 
 
-from __future__ import absolute_import
+
 
 from bacnet.bacnet import *
--- a/bacnet/bacnet.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/bacnet/bacnet.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # This code is made available on the understanding that it will not be
 # used in safety-critical situations without a full and competent review.
 
-from __future__ import absolute_import
+
 
 import os
 from collections import Counter
--- a/c_ext/CFileEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/c_ext/CFileEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx.stc as stc
 
 from controls.CustomStyledTextCtrl import faces
--- a/c_ext/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/c_ext/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,5 +22,5 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 from c_ext.c_ext import *
--- a/c_ext/c_ext.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/c_ext/c_ext.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +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.
 
-from __future__ import absolute_import
+
 import os
 
 from c_ext.CFileEditor import CFileEditor
--- a/canfestival/NetworkEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/canfestival/NetworkEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +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.
 
-from __future__ import absolute_import
+
 import wx
 
 from networkeditortemplate import NetworkEditorTemplate
--- a/canfestival/SlaveEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/canfestival/SlaveEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +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.
 
-from __future__ import absolute_import
+
 import wx
 
 from subindextable import EditingPanel
--- a/canfestival/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/canfestival/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,5 +22,5 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 from canfestival.canfestival import *
--- a/canfestival/canfestival.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/canfestival/canfestival.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import os
 import sys
 import shutil
@@ -352,7 +352,7 @@
 
     def GetVariableLocationTree(self):
         current_location = self.GetCurrentLocation()
-        nodeindexes = self.SlaveNodes.keys()
+        nodeindexes = list(self.SlaveNodes.keys())
         nodeindexes.sort()
         children = []
         children += [GetSlaveLocationTree(self.Manager.GetCurrentNodeCopy(),
--- a/canfestival/config_utils.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/canfestival/config_utils.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,12 +23,13 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import sys
 import getopt
-from past.builtins import long
+from past.builtins import int
+from functools import reduce
 
 # Translation between IEC types and Can Open types
 IECToCOType = {
@@ -63,7 +64,7 @@
 VariableIncrement = 0x100
 VariableStartIndex = {TPDO: 0x2000, RPDO: 0x4000}
 VariableDirText = {TPDO: "__I", RPDO: "__Q"}
-VariableTypeOffset = dict(zip(["", "X", "B", "W", "D", "L"], range(6)))
+VariableTypeOffset = dict(list(zip(["", "X", "B", "W", "D", "L"], list(range(6)))))
 
 TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
 
@@ -85,7 +86,7 @@
     """
 
     data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
-    list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
+    list_car = [data[i:i+2] for i in range(0, len(data), 2)]
     list_car.reverse()
     return "".join([chr(int(car, 16)) for car in list_car])
 
@@ -170,7 +171,7 @@
         # Dictionary of location informations classed by name
         self.MasterMapping = {}
         # List of COB IDs available
-        self.ListCobIDAvailable = range(0x180, 0x580)
+        self.ListCobIDAvailable = list(range(0x180, 0x580))
         # Dictionary of mapping value where unexpected variables are stored
         self.TrashVariables = {}
         # Dictionary of pointed variables
@@ -303,7 +304,7 @@
             values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200)
             if values is not None and values[0] > 0:
                 # Check that all subindex upper than 0 equal 0 => configurable PDO
-                if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True):
+                if reduce(lambda x, y: x and y, [x == 0 for x in values[1:]], True):
                     cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1)
                     # If no COB ID defined in PDO, generate a new one (not used)
                     if cobid == 0:
@@ -374,7 +375,7 @@
                 nodeid, index, subindex = loc[:3]
 
                 # Check Id is in slave node list
-                if nodeid not in self.NodeList.SlaveNodes.keys():
+                if nodeid not in list(self.NodeList.SlaveNodes.keys()):
                     raise PDOmappingException(
                         _("Non existing node ID : {a1} (variable {a2})").
                         format(a1=nodeid, a2=name))
@@ -430,7 +431,7 @@
         #                         Search for locations already mapped
         # -------------------------------------------------------------------------------
 
-        for name, locationinfos in self.IECLocations.items():
+        for name, locationinfos in list(self.IECLocations.items()):
             node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"]
 
             # Search if slave has a PDO mapping this locations
@@ -441,7 +442,7 @@
                 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1)
 
                 # Add PDO to MasterMapping
-                if cobid not in self.MasterMapping.keys():
+                if cobid not in list(self.MasterMapping.keys()):
                     # Verify that PDO transmit type is conform to sync_TPDOs
                     transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2)
                     if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF:
@@ -474,7 +475,7 @@
 
             else:
                 # Add location to those that haven't been mapped yet
-                if locationinfos["nodeid"] not in self.LocationsNotMapped.keys():
+                if locationinfos["nodeid"] not in list(self.LocationsNotMapped.keys()):
                     self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO: [], RPDO: []}
                 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos))
 
@@ -482,7 +483,7 @@
         #                         Build concise DCF for the others locations
         # -------------------------------------------------------------------------------
 
-        for nodeid, locations in self.LocationsNotMapped.items():
+        for nodeid, locations in list(self.LocationsNotMapped.items()):
             node = self.NodeList.SlaveNodes[nodeid]["Node"]
 
             # Initialize number of params and data to add to node DCF
@@ -531,7 +532,7 @@
         # -------------------------------------------------------------------------------
 
         # Generate Master's Configuration from informations stored in MasterMapping
-        for cobid, pdo_infos in self.MasterMapping.items():
+        for cobid, pdo_infos in list(self.MasterMapping.items()):
             # Get next PDO index in MasterNode for this PDO type
             current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]]
 
@@ -572,7 +573,7 @@
                     continue
                 new_index = False
 
-                if isinstance(variable, (int, long)):
+                if isinstance(variable, int):
                     # If variable is an integer then variable is unexpected
                     self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
                 else:
@@ -735,7 +736,7 @@
 
     # Extract workspace base folder
     base_folder = sys.path[0]
-    for i in xrange(3):
+    for i in range(3):
         base_folder = os.path.split(base_folder)[0]
     # Add CanFestival folder to search pathes
     sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
--- a/connectors/ConnectorBase.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/ConnectorBase.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import hashlib
 
 
--- a/connectors/PYRO/PSK_Adapter.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/PYRO/PSK_Adapter.py	Fri Oct 28 12:39:15 2022 +0800
@@ -28,8 +28,8 @@
 but using Pre Shared Keys instead of Certificates
 """
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 
 import socket
 import re
--- a/connectors/PYRO/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/PYRO/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import traceback
 from time import sleep
 import copy
@@ -39,6 +39,7 @@
 import PSKManagement as PSK
 from connectors.PYRO.PSK_Adapter import setupPSKAdapter
 from runtime import PlcStatus
+import importlib
 
 
 def switch_pyro_adapter(use_ssl):
@@ -47,7 +48,7 @@
     This is workaround for Pyro, because it doesn't work with SSL wrapper.
     """
     # Pyro.config.PYRO_BROKEN_MSGWAITALL = use_ssl
-    reload(Pyro.protocol)
+    importlib.reload(Pyro.protocol)
     if use_ssl:
         setupPSKAdapter()
 
--- a/connectors/PYRO_dialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/PYRO_dialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 
 from itertools import repeat, islice, chain
 
--- a/connectors/SchemeEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/SchemeEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 
 from functools import partial
 import wx
--- a/connectors/WAMP/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/WAMP/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import sys
 import traceback
 from functools import partial
--- a/connectors/WAMP_dialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/WAMP_dialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 
 from itertools import repeat, islice, chain
 
--- a/connectors/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/connectors/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -26,7 +26,6 @@
 # Package initialisation
 
 
-from __future__ import absolute_import
 import os
 from os import listdir, path
 from connectors.ConnectorBase import ConnectorBase
--- a/controls/CustomEditableListBox.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/CustomEditableListBox.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 import wx.adv
 
--- a/controls/CustomGrid.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/CustomGrid.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 import wx.grid
 
--- a/controls/CustomIntCtrl.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/CustomIntCtrl.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 import wx.lib.intctrl
 
--- a/controls/CustomStyledTextCtrl.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/CustomStyledTextCtrl.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from functools import reduce
 import wx
 import wx.stc
@@ -72,7 +72,7 @@
     new_length = len(new)
     common_length = min(old_length, new_length)
     i = 0
-    for i in xrange(common_length):
+    for i in range(common_length):
         if old[i] != new[i]:
             break
     if old_length < new_length:
@@ -102,7 +102,7 @@
                 x, _y = event.GetPosition()
                 margin_width = reduce(
                     lambda x, y: x + y,
-                    [self.GetMarginWidth(i) for i in xrange(3)],
+                    [self.GetMarginWidth(i) for i in range(3)],
                     0)
                 if x <= margin_width:
                     self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
--- a/controls/CustomTable.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/CustomTable.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 import wx.grid
 
@@ -204,8 +204,8 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            for _row, row_highlights in self.Highlights.iteritems():
-                row_items = row_highlights.items()
+            for _row, row_highlights in self.Highlights.items():
+                row_items = list(row_highlights.items())
                 for col, col_highlights in row_items:
                     if highlight_type in col_highlights:
                         col_highlights.remove(highlight_type)
--- a/controls/CustomToolTip.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/CustomToolTip.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +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.
 
-from __future__ import absolute_import
+
 import wx
 
 from controls.CustomStyledTextCtrl import faces
--- a/controls/CustomTree.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/CustomTree.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import wx
 import wx.lib.agw.customtreectrl as CT
 
--- a/controls/DebugVariablePanel/DebugVariableGraphicViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/DebugVariableGraphicViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from time import time as gettime
 from cycler import cycler
 
@@ -44,7 +44,7 @@
 
 
 # Graph variable display type
-GRAPH_PARALLEL, GRAPH_ORTHOGONAL = range(2)
+GRAPH_PARALLEL, GRAPH_ORTHOGONAL = list(range(2))
 
 # Canvas height
 [SIZE_MINI, SIZE_MIDDLE, SIZE_MAXI] = [0, 100, 200]
@@ -567,7 +567,7 @@
         """
         start_tick, end_tick = self.ParentWindow.GetRange()
         cursor_tick = None
-        items = self.ItemsDict.values()
+        items = list(self.ItemsDict.values())
 
         # Graph is orthogonal
         if self.GraphType == GRAPH_ORTHOGONAL:
@@ -641,7 +641,7 @@
                 # parent
                 xw, yw = self.GetPosition()
                 self.ParentWindow.StartDragNDrop(
-                    self, self.ItemsDict.values()[item_idx],
+                    self, list(self.ItemsDict.values())[item_idx],
                     x + xw, y + yw,  # Current mouse position
                     x + xw, y + yw)  # Mouse position when button was clicked
 
@@ -679,7 +679,7 @@
         if self.ParentWindow.IsDragging():
             _width, height = self.GetSize()
             xw, yw = self.GetPosition()
-            item = self.ParentWindow.DraggingAxesPanel.ItemsDict.values()[0]
+            item = list(self.ParentWindow.DraggingAxesPanel.ItemsDict.values())[0]
             # Give mouse position in wx coordinate of parent
             self.ParentWindow.StopDragNDrop(item.GetVariable(),
                                             xw + event.x, yw + height - event.y)
@@ -746,7 +746,7 @@
             # If mouse is over an item label,
             if item_idx is not None:
                 self.PopupContextualButtons(
-                    self.ItemsDict.values()[item_idx],
+                    list(self.ItemsDict.values())[item_idx],
                     rect, menu_direction)
                 return
 
@@ -784,7 +784,7 @@
                     xw, yw = self.GetPosition()
                     self.ParentWindow.SetCursorTick(self.StartCursorTick)
                     self.ParentWindow.StartDragNDrop(
-                        self, self.ItemsDict.values()[0],
+                        self, list(self.ItemsDict.values())[0],
                         # Current mouse position
                         event.x + xw, height - event.y + yw,
                         # Mouse position when button was clicked
@@ -1029,7 +1029,7 @@
         # Graph type is parallel or orthogonal in 3D
         if self.GraphType == GRAPH_PARALLEL or self.Is3DCanvas():
             num_item = len(self.Items)
-            for idx in xrange(num_item):
+            for idx in range(num_item):
 
                 # Get color from color cycle (black if only one item)
                 color = ('k' if num_item == 1 else
@@ -1093,7 +1093,7 @@
         # Update position of items labels
         if self.GraphType == GRAPH_PARALLEL or self.Is3DCanvas():
             num_item = len(self.Items)
-            for idx in xrange(num_item):
+            for idx in range(num_item):
 
                 # In 3D graph items variable label are not displayed
                 if not self.Is3DCanvas():
@@ -1189,7 +1189,7 @@
                 # each variable
                 start_tick = max(start_tick, self.GetItemsMinCommonTick())
                 end_tick = max(end_tick, start_tick)
-                items = self.ItemsDict.values()
+                items = list(self.ItemsDict.values())
 
                 # Get data and range for first variable (X coordinate)
                 x_data, x_min, x_max = items[0].GetDataAndValueRange(
@@ -1331,7 +1331,7 @@
             item.GetValue(self.CursorTick)
             if self.CursorTick is not None
             else (item.GetValue(), item.IsForced())) for item in self.Items]
-        values, forced = zip(*args)
+        values, forced = list(zip(*args))
 
         # Get path of each variable displayed simplified using panel variable
         # name mask
@@ -1339,7 +1339,7 @@
                   for item in self.Items]
 
         # Get style for each variable according to
-        styles = map(lambda x: {True: 'italic', False: 'normal'}[x], forced)
+        styles = [{True: 'italic', False: 'normal'}[x] for x in forced]
 
         # Graph is orthogonal 3D, set variables path as 3D axis label
         if self.Is3DCanvas():
--- a/controls/DebugVariablePanel/DebugVariableItem.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/DebugVariableItem.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from datetime import timedelta
 import binascii
 import numpy as np
--- a/controls/DebugVariablePanel/DebugVariablePanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/DebugVariablePanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from functools import reduce
 import numpy as np
 
--- a/controls/DebugVariablePanel/DebugVariableTextViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/DebugVariableTextViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 
 import wx
 
@@ -207,7 +207,7 @@
         gc = wx.GCDC(dc)
 
         # Get first item
-        item = self.ItemsDict.values()[0]
+        item = list(self.ItemsDict.values())[0]
 
         # Get item variable path masked according Debug Variable Panel mask
         item_path = item.GetVariable(
@@ -239,7 +239,7 @@
         @param event: wx.MouseEvent
         """
         # Get first item
-        item = self.ItemsDict.values()[0]
+        item = list(self.ItemsDict.values())[0]
 
         # Calculate item path bounding box
         _width, height = self.GetSize()
@@ -278,7 +278,7 @@
         @param event: wx.MouseEvent
         """
         # Only numeric variables can be toggled to graph canvas
-        if self.ItemsDict.values()[0].IsNumVariable():
+        if list(self.ItemsDict.values())[0].IsNumVariable():
             self.ParentWindow.ToggleViewerType(self)
 
     def OnPaint(self, event):
--- a/controls/DebugVariablePanel/DebugVariableViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/DebugVariableViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from collections import OrderedDict
 from functools import reduce
 
@@ -39,7 +39,7 @@
  HIGHLIGHT_AFTER,
  HIGHLIGHT_LEFT,
  HIGHLIGHT_RIGHT,
- HIGHLIGHT_RESIZE] = range(6)
+ HIGHLIGHT_RESIZE] = list(range(6))
 
 # Viewer highlight styles
 HIGHLIGHT = {
@@ -66,7 +66,7 @@
         items = [] if items is None else items
         self.ItemsDict = OrderedDict([(item.GetVariable(), item)
                                       for item in items])
-        self.Items = self.ItemsDict.viewvalues()
+        self.Items = self.ItemsDict.values()
 
         # Variable storing current highlight displayed in Viewer
         self.Highlight = HIGHLIGHT_NONE
@@ -111,7 +111,7 @@
         Return items displayed by Viewer
         @return: List of items displayed in Viewer
         """
-        return self.ItemsDict.values()
+        return list(self.ItemsDict.values())
 
     def AddItem(self, item):
         """
@@ -150,7 +150,7 @@
         Function that unsubscribe and remove every item that store values of
         a variable that doesn't exist in PLC anymore
         """
-        for item in self.ItemsDict.values()[:]:
+        for item in list(self.ItemsDict.values())[:]:
             iec_path = item.GetVariable()
 
             # Check that variablepath exist in PLC
@@ -347,13 +347,13 @@
         """
         Function called when Force button is pressed
         """
-        self.ForceValue(self.ItemsDict.values()[0])
+        self.ForceValue(list(self.ItemsDict.values())[0])
 
     def OnReleaseButton(self):
         """
         Function called when Release button is pressed
         """
-        self.ReleaseValue(self.ItemsDict.values()[0])
+        self.ReleaseValue(list(self.ItemsDict.values())[0])
 
     def OnMouseDragging(self, x, y):
         """
--- a/controls/DebugVariablePanel/GraphButton.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/GraphButton.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from util.BitmapLibrary import GetBitmap
--- a/controls/DebugVariablePanel/RingBuffer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/RingBuffer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -44,7 +44,7 @@
         note: only when this function is called, is an O(size) performance hit incurred,
         and this cost is amortized over the whole padding space
         """
-        print 'compacting'
+        print('compacting')
         self.buffer[:self.count] = self.view
         self.cursor -= self.size
 
--- a/controls/DebugVariablePanel/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DebugVariablePanel/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,5 +22,5 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 from controls.DebugVariablePanel.DebugVariablePanel import DebugVariablePanel
--- a/controls/DiscoveryPanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DiscoveryPanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import socket
 from six.moves import xrange
 import wx
@@ -203,8 +203,7 @@
         if self.LatestSelection is not None:
             # if self.ByIPCheck.IsChecked():
             svcname, scheme, host, port = \
-                map(lambda col: self.getColumnText(self.LatestSelection, col),
-                    range(4))
+                [self.getColumnText(self.LatestSelection, col) for col in range(4)]
             return ("%s://%s:%s#%s" % (scheme, host, port, svcname)) \
                 if scheme[-1] == "S" \
                 else ("%s://%s:%s" % (scheme, host, port))
@@ -223,7 +222,7 @@
         '''
 
         # loop through the list items looking for the service that went offline
-        for idx in xrange(self.ServicesList.GetItemCount()):
+        for idx in range(self.ServicesList.GetItemCount()):
             # this is the unique identifier assigned to the item
             item_id = self.ServicesList.GetItemData(idx)
 
--- a/controls/DurationCellEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/DurationCellEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from dialogs.DurationEditorDialog import DurationEditorDialog
--- a/controls/EnhancedStatusBar.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/EnhancedStatusBar.py	Fri Oct 28 12:39:15 2022 +0800
@@ -55,8 +55,8 @@
 
 """
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import wx
 
 # Horizontal Alignment Constants
@@ -109,7 +109,7 @@
         Actually, All The Calculations Linked To HorizontalAlignment And
         VerticalAlignment Are Done In This Function."""
 
-        for pos, item in self._items.items():
+        for pos, item in list(self._items.items()):
             widget, horizontalalignment, verticalalignment = item.widget, item.horizontalalignment, item.verticalalignment
 
             rect = self.GetFieldRect(pos)
--- a/controls/FolderTree.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/FolderTree.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 
 import wx
@@ -31,7 +31,7 @@
 
 from util.BitmapLibrary import GetBitmap
 
-DRIVE, FOLDER, FILE = range(3)
+DRIVE, FOLDER, FILE = list(range(3))
 
 
 def sort_folder(x, y):
@@ -99,7 +99,7 @@
         self.Filters = {}
         if self.Filter is not None:
             filter_parts = filter.split("|")
-            for idx in xrange(0, len(filter_parts), 2):
+            for idx in range(0, len(filter_parts), 2):
                 if filter_parts[idx + 1] == "*.*":
                     self.Filters[filter_parts[idx]] = ""
                 else:
@@ -115,7 +115,7 @@
     def _GetFolderChildren(self, folderpath, recursive=True):
         items = []
         if wx.Platform == '__WXMSW__' and folderpath == "/":
-            for c in xrange(ord('a'), ord('z')):
+            for c in range(ord('a'), ord('z')):
                 drive = os.path.join("%s:\\" % chr(c))
                 if os.path.exists(drive):
                     items.append((drive, DRIVE, self._GetFolderChildren(drive, False)))
--- a/controls/IDBrowser.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/IDBrowser.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import wx
 import wx.dataview as dv
 import PSKManagement as PSK
--- a/controls/LibraryPanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/LibraryPanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +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.
 
-from __future__ import absolute_import
+
 from functools import reduce
 import wx
 
@@ -31,7 +31,7 @@
 # -------------------------------------------------------------------------------
 
 
-[CATEGORY, BLOCK] = range(2)
+[CATEGORY, BLOCK] = list(range(2))
 
 
 # -------------------------------------------------------------------------------
@@ -346,12 +346,10 @@
             if inputs is not None and type_inputs is not None:
                 same_inputs = reduce(
                     lambda x, y: x and y,
-                    map(
-                        lambda x: x[0] == x[1] or x[0] == 'ANY' or x[1] == 'ANY',
-                        zip(type_inputs,
+                    [x[0] == x[1] or x[0] == 'ANY' or x[1] == 'ANY' for x in zip(type_inputs,
                             (inputs[:type_extension]
                              if type_extension is not None
-                             else inputs))),
+                             else inputs))],
                     True)
             else:
                 same_inputs = True
--- a/controls/LocationCellEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/LocationCellEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from dialogs.BrowseLocationsDialog import BrowseLocationsDialog
--- a/controls/LogViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/LogViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from datetime import datetime
 from time import time as gettime
 from weakref import proxy
@@ -370,7 +370,7 @@
         self.ParentWindow = window
 
         self.LevelIcons = [GetBitmap("LOG_" + level) for level in LogLevels]
-        self.LevelFilters = [range(i) for i in xrange(4, 0, -1)]
+        self.LevelFilters = [list(range(i)) for i in range(4, 0, -1)]
         self.CurrentFilter = self.LevelFilters[0]
         self.CurrentSearchValue = ""
 
@@ -415,14 +415,14 @@
 
     def SetLogCounters(self, log_count):
         new_messages = []
-        for level, count, prev in zip(xrange(LogLevelsCount), log_count, self.previous_log_count):
+        for level, count, prev in zip(range(LogLevelsCount), log_count, self.previous_log_count):
             if count is not None and prev != count:
                 if prev is None:
                     dump_end = max(-1, count - 10)
                     oldest_message = (-1, None)
                 else:
                     dump_end = prev - 1
-                for msgidx in xrange(count-1, dump_end, -1):
+                for msgidx in range(count-1, dump_end, -1):
                     new_message = self.GetLogMessageFromSource(msgidx, level)
                     if new_message is None:
                         if prev is None:
@@ -560,7 +560,7 @@
 
     def IsPLCLogEmpty(self):
         empty = True
-        for _level, prev in zip(xrange(LogLevelsCount), self.previous_log_count):
+        for _level, prev in zip(range(LogLevelsCount), self.previous_log_count):
             if prev is not None:
                 empty = False
                 break
--- a/controls/PouInstanceVariablesPanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/PouInstanceVariablesPanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from collections import namedtuple
 
 import wx
--- a/controls/ProjectPropertiesPanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/ProjectPropertiesPanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 import wx
 from wx.lib.scrolledpanel import ScrolledPanel
 
@@ -38,7 +38,7 @@
 [
     TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
     POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
-] = range(10)
+] = list(range(10))
 
 
 # -------------------------------------------------------------------------------
@@ -246,7 +246,7 @@
 
     def SetValues(self, values):
         self.Values = values
-        for item, value in values.items():
+        for item, value in list(values.items()):
             if item == "language":
                 self.Language.SetStringSelection(value)
             elif item == "contentDescription":
@@ -255,7 +255,7 @@
                 self.PageWidth.SetValue(value[0])
                 self.PageHeight.SetValue(value[1])
             elif item == "scaling":
-                for language, (x, y) in value.items():
+                for language, (x, y) in list(value.items()):
                     if language in self.Scalings:
                         self.Scalings[language][0].SetValue(x)
                         self.Scalings[language][1].SetValue(y)
--- a/controls/SearchResultPanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/SearchResultPanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from functools import reduce
 
 import wx
@@ -289,7 +289,7 @@
             start, end = infos["data"][1:3]
             text_lines = infos["text"].splitlines()
             start_idx = start[1]
-            end_idx = reduce(lambda x, y: x + y, map(lambda x: len(x) + 1, text_lines[:end[0] - start[0]]), end[1] + 1)
+            end_idx = reduce(lambda x, y: x + y, [len(x) + 1 for x in text_lines[:end[0] - start[0]]], end[1] + 1)
             style = wx.TextAttr(wx.BLACK, wx.Colour(206, 204, 247))
         elif infos["type"] is not None and infos["matches"] > 1:
             text = _("(%d matches)") % infos["matches"]
--- a/controls/TextCtrlAutoComplete.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/TextCtrlAutoComplete.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from six.moves import cPickle
 import wx
 
--- a/controls/VariablePanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/VariablePanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import re
 from builtins import str as text
 
@@ -54,7 +54,7 @@
 [
     TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
     POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
-] = range(10)
+] = list(range(10))
 
 
 def GetVariableTableColnames(location):
@@ -123,7 +123,7 @@
         self.OPTIONS_DICT = dict([(_(option), option)
                                   for option in GetOptions()])
         self.VARIABLE_CLASSES_DICT = dict([(_(_class), _class)
-                                           for _class in GetFilterChoiceTransfer().itervalues()])
+                                           for _class in GetFilterChoiceTransfer().values()])
 
     def GetValueByName(self, row, colname):
         if row < self.GetNumberRows():
@@ -200,7 +200,7 @@
                                              retain=self.Parent.ElementType != "function" and var_class in ["Local", "Input", "Output", "Global"],
                                              non_retain=self.Parent.ElementType != "function" and var_class in ["Local", "Input", "Output"])
                         if len(options) > 1:
-                            editor = wx.grid.GridCellChoiceEditor(map(_, options))
+                            editor = wx.grid.GridCellChoiceEditor(list(map(_, options)))
                         else:
                             grid.SetReadOnly(row, col, True)
                     elif col != 0 and self._GetRowEdit(row):
@@ -447,7 +447,7 @@
         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
 
         self.VARIABLE_CHOICES_DICT = dict([(_(_class), _class) for
-                                           _class in GetFilterChoiceTransfer().iterkeys()])
+                                           _class in GetFilterChoiceTransfer().keys()])
 
         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0)
         self.MainSizer.AddGrowableCol(0)
@@ -581,7 +581,7 @@
             self.ClassFilter.Append(_(choice))
 
         reverse_transfer = {}
-        for filter, choice in self.FilterChoiceTransfer.items():
+        for filter, choice in list(self.FilterChoiceTransfer.items()):
             reverse_transfer[choice] = filter
         self.ClassFilter.SetStringSelection(_(reverse_transfer[self.Filter]))
         self.RefreshTypeList()
@@ -995,7 +995,7 @@
 
     def AddVariableHighlight(self, infos, highlight_type):
         if isinstance(infos[0], tuple):
-            for i in xrange(*infos[0]):
+            for i in range(*infos[0]):
                 self.Table.AddHighlight((i,) + infos[1:], highlight_type)
             cell_visible = infos[0][0]
         else:
@@ -1007,7 +1007,7 @@
 
     def RemoveVariableHighlight(self, infos, highlight_type):
         if isinstance(infos[0], tuple):
-            for i in xrange(*infos[0]):
+            for i in range(*infos[0]):
                 self.Table.RemoveHighlight((i,) + infos[1:], highlight_type)
         else:
             self.Table.RemoveHighlight(infos, highlight_type)
--- a/controls/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/controls/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 
 # Package initialization
 
-from __future__ import absolute_import
+
 
 from controls.CustomEditableListBox import CustomEditableListBox
 from controls.CustomGrid import CustomGrid
--- a/dialogs/AboutDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/AboutDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -31,7 +31,7 @@
 """
 
 
-from __future__ import absolute_import
+
 import os
 import wx
 import wx.adv
@@ -122,8 +122,8 @@
         developer = wx.TextCtrl(notebook, style=wx.TE_READONLY | wx.TE_MULTILINE)
         translators = wx.TextCtrl(notebook, style=wx.TE_READONLY | wx.TE_MULTILINE)
 
-        developer.SetValue(u'\n'.join(info.Developers))
-        translators.SetValue(u'\n'.join(info.Translators))
+        developer.SetValue('\n'.join(info.Developers))
+        translators.SetValue('\n'.join(info.Translators))
 
         notebook.AddPage(developer, text=_("Written by"))
         notebook.AddPage(translators, text=_("Translated by"))
--- a/dialogs/ActionBlockDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/ActionBlockDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 import wx.grid
 import wx.lib.buttons
@@ -162,7 +162,7 @@
 
         self.Table = ActionTable(self, [], GetActionTableColnames())
         typelist = GetTypeList()
-        self.TypeList = map(_, typelist)
+        self.TypeList = list(map(_, typelist))
         self.TranslateType = dict([(_(value), value) for value in typelist])
         self.ColSizes = [60, 90, 130, 200, 50]
         self.ColAlignements = [wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
--- a/dialogs/ArrayTypeDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/ArrayTypeDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +22,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import re
 
 import wx
@@ -84,7 +84,7 @@
 
         if isinstance(infos, tuple) and infos[0] == "array":
             self.BaseType.SetStringSelection(infos[1])
-            self.Dimensions.SetStrings(map("..".join, infos[2]))
+            self.Dimensions.SetStrings(list(map("..".join, infos[2])))
         elif infos in datatypes:
             self.BaseType.SetStringSelection(infos)
 
--- a/dialogs/BlockPreviewDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/BlockPreviewDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import wx
 
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
--- a/dialogs/BrowseLocationsDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/BrowseLocationsDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.#
 
 
-from __future__ import absolute_import
+
 import wx
 
 from plcopen.structures import LOCATIONDATATYPES
@@ -54,7 +54,7 @@
 
 # turn LOCATIONDATATYPES inside-out
 LOCATION_SIZES = {}
-for size, types in LOCATIONDATATYPES.iteritems():
+for size, types in LOCATIONDATATYPES.items():
     for type in types:
         LOCATION_SIZES[type] = size
 
--- a/dialogs/BrowseValuesLibraryDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/BrowseValuesLibraryDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 
--- a/dialogs/CommentEditDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/CommentEditDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -20,7 +20,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 
 import wx
 
--- a/dialogs/ConnectionDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/ConnectionDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.GraphicCommons import CONNECTOR, CONTINUATION
@@ -127,7 +127,7 @@
         @param values: Connection parameters values
         """
         # For each parameters defined, set corresponding control value
-        for name, value in values.items():
+        for name, value in list(values.items()):
 
             # Parameter is connection type
             if name == "type":
--- a/dialogs/DurationEditorDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/DurationEditorDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import re
 
 import wx
--- a/dialogs/FBDBlockDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/FBDBlockDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import re
 
 import wx
@@ -177,7 +177,7 @@
         default_name_model = GetBlockTypeDefaultNameModel(blocktype)
 
         # For each parameters defined, set corresponding control value
-        for name, value in values.items():
+        for name, value in list(values.items()):
 
             # Parameter is block name
             if name == "name":
@@ -212,7 +212,7 @@
         values["width"], values["height"] = self.Element.GetSize()
         values.update({
             name: control.GetValue()
-            for name, control in self.ParamsControl.iteritems()})
+            for name, control in self.ParamsControl.items()})
         return values
 
     def OnOK(self, event):
--- a/dialogs/FBDVariableDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/FBDVariableDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.GraphicCommons import INPUT, INOUT, OUTPUT
@@ -66,7 +66,7 @@
         }
 
         self.VARIABLE_CLASSES_DICT_REVERSE = dict(
-            [(value, key) for key, value in self.VARIABLE_CLASSES_DICT.iteritems()])
+            [(value, key) for key, value in self.VARIABLE_CLASSES_DICT.items()])
 
         # Init common sizers
         self._init_sizers(4, 2, 4, None, 3, 2)
@@ -120,7 +120,7 @@
             flag=wx.ALIGN_RIGHT | wx.BOTTOM | wx.LEFT | wx.RIGHT)
 
         # Set options that can be selected in class combo box
-        for var_class, choice in self.VARIABLE_CLASSES_DICT.iteritems():
+        for var_class, choice in self.VARIABLE_CLASSES_DICT.items():
             if not exclude_input or var_class != INPUT:
                 self.Class.Append(choice)
         self.Class.SetSelection(0)
@@ -148,7 +148,7 @@
         # Refresh names in name list box by selecting variables in POU variables
         # list that can be applied to variable class
         self.VariableName.Clear()
-        for name, (var_type, _value_type) in self.VariableList.iteritems():
+        for name, (var_type, _value_type) in self.VariableList.items():
             if var_type != "Input" or var_class == INPUT:
                 self.VariableName.Append(name)
 
@@ -178,7 +178,7 @@
             self.RefreshNameList()
 
         # For each parameters defined, set corresponding control value
-        for name, value in values.items():
+        for name, value in list(values.items()):
 
             # Parameter is variable expression
             if name == "expression":
--- a/dialogs/FindInPouDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/FindInPouDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 from plcopen.plcopen import *
 
--- a/dialogs/ForceVariableDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/ForceVariableDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +22,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import re
 import datetime
 from builtins import str as text
--- a/dialogs/IDManager.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/IDManager.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,4 +1,4 @@
-from __future__ import absolute_import
+
 
 import wx
 from controls.IDBrowser import IDBrowser
--- a/dialogs/IDMergeDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/IDMergeDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import wx
 
 
--- a/dialogs/LDElementDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/LDElementDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.GraphicCommons import CONTACT_NORMAL, CONTACT_REVERSE, \
@@ -117,7 +117,7 @@
         self.RefreshVariableList()
 
         # Set values in ElementVariable
-        for name, (var_type, value_type) in self.VariableList.iteritems():
+        for name, (var_type, value_type) in self.VariableList.items():
             # Only select BOOL variable and avoid input for coil
             if (type == "contact" or var_type != "Input") and \
                value_type == "BOOL":
@@ -134,7 +134,7 @@
         """
         # Go through radio buttons and return modifier associated to the one
         # that is selected
-        for modifier, control in self.ModifierRadioButtons.iteritems():
+        for modifier, control in self.ModifierRadioButtons.items():
             if control.GetValue():
                 return modifier
         return None
@@ -145,7 +145,7 @@
         @param values: LD element parameters values
         """
         # For each parameters defined, set corresponding control value
-        for name, value in values.items():
+        for name, value in list(values.items()):
 
             # Parameter is LD element variable
             if name == "variable":
--- a/dialogs/LDPowerRailDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/LDPowerRailDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.GraphicCommons import LEFTRAIL, RIGHTRAIL
@@ -118,7 +118,7 @@
         @param values: Power rail parameters values
         """
         # For each parameters defined, set corresponding control value
-        for name, value in values.items():
+        for name, value in list(values.items()):
 
             # Parameter is power rail type
             if name == "type":
--- a/dialogs/MessageBoxOnce.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/MessageBoxOnce.py	Fri Oct 28 12:39:15 2022 +0800
@@ -7,7 +7,7 @@
 # See COPYING file for copyrights details.
 
 
-from __future__ import absolute_import
+
 import wx
 
 
--- a/dialogs/PouActionDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/PouActionDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
@@ -121,7 +121,7 @@
         self.PouElementNames = [element_name.upper() for element_name in element_names]
 
     def SetValues(self, values):
-        for item, value in values.items():
+        for item, value in list(values.items()):
             if item == "actionName":
                 self.ActionName.SetValue(value)
             elif item == "language":
--- a/dialogs/PouDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/PouDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
@@ -201,7 +201,7 @@
         self.PouElementNames = [element_name.upper() for element_name in element_names]
 
     def SetValues(self, values):
-        for item, value in values.items():
+        for item, value in list(values.items()):
             if item == "pouName":
                 self.PouName.SetValue(value)
             elif item == "pouType":
--- a/dialogs/PouNameDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/PouNameDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
 
--- a/dialogs/PouTransitionDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/PouTransitionDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
@@ -123,7 +123,7 @@
         self.PouElementNames = [pou_name.upper() for pou_name in pou_names]
 
     def SetValues(self, values):
-        for item, value in values.items():
+        for item, value in list(values.items()):
             if item == "transitionName":
                 self.TransitionName.SetValue(value)
             elif item == "language":
--- a/dialogs/ProjectDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/ProjectDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from controls.ProjectPropertiesPanel import ProjectPropertiesPanel
--- a/dialogs/SFCDivergenceDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/SFCDivergenceDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.GraphicCommons import SELECTION_DIVERGENCE, \
@@ -126,7 +126,7 @@
         """
         # Go through radio buttons and return type associated to the one that
         # is selected
-        for type, control in self.TypeRadioButtons.iteritems():
+        for type, control in self.TypeRadioButtons.items():
             if control.GetValue():
                 return type
         return None
--- a/dialogs/SFCStepDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/SFCStepDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.SFC_Objects import SFC_Step
@@ -107,7 +107,7 @@
         @param values: Block parameters values
         """
         # For each parameters defined, set corresponding control value
-        for name, value in values.items():
+        for name, value in list(values.items()):
 
             # Parameter is step name
             if name == "name":
@@ -130,7 +130,7 @@
         values = {"name": self.StepName.GetValue()}
         values.update({
             name: control.IsChecked()
-            for name, control in self.ConnectorsCheckBox.iteritems()})
+            for name, control in self.ConnectorsCheckBox.items()})
         values["width"], values["height"] = self.Element.GetSize()
         return values
 
@@ -185,7 +185,7 @@
                                 self.Initial)
 
         # Update connectors of SFC step element according to check boxes value
-        for name, control in self.ConnectorsCheckBox.iteritems():
+        for name, control in self.ConnectorsCheckBox.items():
             if control.IsChecked():
                 getattr(self.Element, "Add" + name.capitalize())()
             else:
--- a/dialogs/SFCStepNameDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/SFCStepNameDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
 
--- a/dialogs/SFCTransitionDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/SFCTransitionDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.SFC_Objects import SFC_Transition
@@ -117,7 +117,7 @@
         """
         # Go through radio buttons and return type and value associated to the
         # one that is selected
-        for type, (radio, control) in self.TypeRadioButtons.iteritems():
+        for type, (radio, control) in self.TypeRadioButtons.items():
             if radio.GetValue():
                 if isinstance(control, wx.ComboBox):
                     return type, control.GetStringSelection()
@@ -136,7 +136,7 @@
         type_value = values.get("value", None)
 
         # For each parameters defined, set corresponding control value
-        for name, value in values.items():
+        for name, value in list(values.items()):
 
             # Parameter is SFC transition priority
             if name == "priority":
@@ -144,7 +144,7 @@
 
             # Parameter is SFC transition type
             elif name == "type":
-                for type, (radio, control) in self.TypeRadioButtons.iteritems():
+                for type, (radio, control) in self.TypeRadioButtons.items():
                     radio.SetValue(type == value)
                     if control is not None:
                         # Enable associated control to type and set value
@@ -197,7 +197,7 @@
         @param event: wx.RadioButtonEvent
         """
         # Refresh sensibility of control associated to transition types
-        for _type, (radio, control) in self.TypeRadioButtons.iteritems():
+        for _type, (radio, control) in self.TypeRadioButtons.items():
             if control is not None:
                 control.Enable(radio.GetValue())
 
--- a/dialogs/SearchInProjectDialog.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/SearchInProjectDialog.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 from plcopen.plcopen import *
 from util.TranslationCatalogs import NoTranslate
--- a/dialogs/UriEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/UriEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,4 +1,4 @@
-from __future__ import absolute_import
+
 
 import wx
 from connectors import ConnectorSchemes, EditorClassFromScheme
--- a/dialogs/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/dialogs/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -25,7 +25,7 @@
 
 # Package initialization
 
-from __future__ import absolute_import
+
 
 from dialogs.CommentEditDialog import CommentEditDialog
 from dialogs.ConnectionDialog import ConnectionDialog
--- a/docutil/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/docutil/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from docutil.dochtml import *
 from docutil.docpdf import *
 from docutil.docsvg import *
--- a/docutil/dochtml.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/docutil/dochtml.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import subprocess
 import wx
 import wx.html
--- a/docutil/docpdf.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/docutil/docpdf.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import wx
 
--- a/docutil/docsvg.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/docutil/docsvg.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import wx
 import subprocess
@@ -75,8 +75,8 @@
     inkpath = get_inkscape_path()
     if inkpath is None:
         return None
-    return map(int, 
-        subprocess.check_output([inkpath,"--version"]).split()[1].split('.'))
+    return list(map(int, 
+        subprocess.check_output([inkpath,"--version"]).split()[1].split('.')))
 
 _inkscape_version = None
 def get_inkscape_version():
@@ -88,7 +88,7 @@
     _inkscape_version = _get_inkscape_version()
     return _inkscape_version
 
-if os.environ.has_key("SNAP"):
+if "SNAP" in os.environ:
     def open_svg(svgfile):
         MessageBoxOnce("Launching Inkscape with xdg-open",
                 "Confined app can't launch Inkscape directly.\n"+
--- a/editors/CodeFileEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/CodeFileEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import re
 from builtins import str as text
 
@@ -46,7 +46,7 @@
 
 
 [STC_CODE_ERROR, STC_CODE_SEARCH_RESULT,
- STC_CODE_SECTION] = range(15, 18)
+ STC_CODE_SECTION] = list(range(15, 18))
 
 HIGHLIGHT_TYPES = {
     ERROR_HIGHLIGHT: STC_CODE_ERROR,
@@ -285,7 +285,7 @@
     def RefreshSectionStyling(self):
         self.Colourise(0, -1)
 
-        for line in xrange(self.GetLineCount()):
+        for line in range(self.GetLineCount()):
             self.SetLineState(line, 0)
 
         doc_end_pos = self.GetLength()
@@ -627,8 +627,8 @@
         super(VariablesTable, self).__init__(*args, **kwargs)
         self.columnTypes = dict(self.__defaultColumnType)
         if my_columns is not None:
-            for key in my_columns.keys():
-                if key in self.columnTypes.keys():
+            for key in list(my_columns.keys()):
+                if key in list(self.columnTypes.keys()):
                     self.columnTypes[key] = my_columns[key]
 
     def GetValue(self, row, col):
--- a/editors/ConfTreeNodeEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/ConfTreeNodeEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 
 import wx
 
--- a/editors/DataTypeEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/DataTypeEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import re
 from six.moves import xrange
 
@@ -239,7 +239,7 @@
         subrange_panel_sizer.Add(self.SubrangeMinimum, 1, border=5,
                                        flag=wx.GROW | wx.ALL)
 
-        for dummy in xrange(2):
+        for dummy in range(2):
             subrange_panel_sizer.Add(wx.Size(0, 0), 1)
 
         subrange_maximum_label = wx.StaticText(self.SubrangePanel,
@@ -512,7 +512,7 @@
                 self.EnumeratedInitialValue.SetStringSelection(type_infos["initial"])
             elif type_infos["type"] == "Array":
                 self.ArrayBaseType.SetStringSelection(type_infos["base_type"])
-                self.ArrayDimensions.SetStrings(map("..".join, type_infos["dimensions"]))
+                self.ArrayDimensions.SetStrings(list(map("..".join, type_infos["dimensions"])))
                 self.ArrayInitialValue.SetValue(type_infos["initial"])
             elif type_infos["type"] == "Structure":
                 self.StructureElementsTable.SetData(type_infos["elements"])
@@ -778,7 +778,7 @@
             self.Highlights = []
         else:
             self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
-        for control in self.HighlightControls.itervalues():
+        for control in self.HighlightControls.values():
             if isinstance(control, (wx.ComboBox, wx.SpinCtrl)):
                 control.SetBackgroundColour(wx.NullColour)
                 control.SetForegroundColour(wx.NullColour)
@@ -788,7 +788,7 @@
                 control.SetStyle(0, len(value), wx.TextAttr(wx.NullColour))
             elif isinstance(control, wx.adv.EditableListBox):
                 listctrl = control.GetListCtrl()
-                for i in xrange(listctrl.GetItemCount()):
+                for i in range(listctrl.GetItemCount()):
                     listctrl.SetItemBackgroundColour(i, wx.NullColour)
                     listctrl.SetItemTextColour(i, wx.NullColour)
         self.StructureElementsTable.ClearHighlights(highlight_type)
--- a/editors/DebugViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/DebugViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from threading import Lock, Timer
 from time import time as gettime
 
@@ -130,7 +130,7 @@
         @param inhibit: Inhibit flag
         """
         # Inhibit every data consumers in list
-        for consumer, _iec_path in self.DataConsumers.iteritems():
+        for consumer, _iec_path in self.DataConsumers.items():
             consumer.Inhibit(inhibit)
 
         # Save inhibit flag
@@ -192,7 +192,7 @@
                 self.DataProducer.UnsubscribeDebugIECVariable("__tick__", self)
 
             # Unsubscribe all data consumers in list
-            for consumer, iec_path in self.DataConsumers.iteritems():
+            for consumer, iec_path in self.DataConsumers.items():
                 self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer)
 
         self.DataConsumers = {}
--- a/editors/EditorPanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/EditorPanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from controls import VariablePanel
--- a/editors/FileManagementPanel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/FileManagementPanel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import shutil
 
--- a/editors/IECCodeViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/IECCodeViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from editors.TextViewer import TextViewer
 from plcopen.plcopen import TestTextElement
 
--- a/editors/LDViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/LDViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from future.builtins import round
 
 import wx
@@ -69,7 +69,7 @@
         elif element_tree[element]:
             element_tree[element]["parents"].append("start")
     remove_stops = {"start": [], "stop": []}
-    for element, values in element_tree.items():
+    for element, values in list(element_tree.items()):
         if "stop" in values["children"]:
             removed = []
             for child in values["children"]:
@@ -88,7 +88,7 @@
         element_tree[element]["parents"].remove("start")
     for element in remove_stops["stop"]:
         element_tree[element]["children"].remove("stop")
-    for element, values in element_tree.items():
+    for element, values in list(element_tree.items()):
         if values and "stop" in values["children"]:
             CalcWeight(element, element_tree)
             if values["weight"]:
@@ -301,7 +301,7 @@
             return Viewer.SearchElements(self, bbox)
 
         elements = []
-        for element in self.Blocks.values() + self.Comments.values():
+        for element in list(self.Blocks.values()) + list(self.Comments.values()):
             if element.IsInSelection(bbox):
                 elements.append(element)
         return elements
@@ -1190,7 +1190,7 @@
 
     def RefreshRungs(self, movey, fromidx):
         if movey != 0:
-            for i in xrange(fromidx, len(self.Rungs)):
+            for i in range(fromidx, len(self.Rungs)):
                 self.RungComments[i].Move(0, movey)
                 self.RungComments[i].RefreshModel()
                 self.Rungs[i].Move(0, movey)
--- a/editors/ProjectNodeEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/ProjectNodeEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from controls import ProjectPropertiesPanel, VariablePanel
--- a/editors/ResourceEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/ResourceEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 import wx.lib.buttons
 import wx.grid
@@ -165,7 +165,7 @@
                     if single != "" and not CheckSingle(single, self.Parent.VariableList):
                         error = True
                 elif colname == "Triggering":
-                    editor = wx.grid.GridCellChoiceEditor(map(_, GetTaskTriggeringOptions()))
+                    editor = wx.grid.GridCellChoiceEditor(list(map(_, GetTaskTriggeringOptions())))
                 elif colname == "Type":
                     editor = wx.grid.GridCellChoiceEditor(self.Parent.TypeList)
                 elif colname == "Priority":
@@ -198,8 +198,8 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            for _row, row_highlights in self.Highlights.iteritems():
-                row_items = row_highlights.items()
+            for _row, row_highlights in self.Highlights.items():
+                row_items = list(row_highlights.items())
                 for col, col_highlights in row_items:
                     if highlight_type in col_highlights:
                         col_highlights.remove(highlight_type)
@@ -230,7 +230,7 @@
         tasks_buttons_sizer.AddGrowableRow(0)
         tasks_sizer.Add(tasks_buttons_sizer, flag=wx.GROW)
 
-        tasks_label = wx.StaticText(self.Editor, label=_(u'Tasks:'))
+        tasks_label = wx.StaticText(self.Editor, label=_('Tasks:'))
         tasks_buttons_sizer.Add(tasks_label, flag=wx.ALIGN_BOTTOM)
 
         for name, bitmap, help in [
@@ -261,7 +261,7 @@
         instances_buttons_sizer.AddGrowableRow(0)
         instances_sizer.Add(instances_buttons_sizer, flag=wx.GROW)
 
-        instances_label = wx.StaticText(self.Editor, label=_(u'Instances:'))
+        instances_label = wx.StaticText(self.Editor, label=_('Instances:'))
         instances_buttons_sizer.Add(instances_label, flag=wx.ALIGN_BOTTOM)
 
         for name, bitmap, help in [
@@ -404,7 +404,7 @@
 
     def RefreshTaskList(self):
         self.TaskList = []
-        for row in xrange(self.TasksTable.GetNumberRows()):
+        for row in range(self.TasksTable.GetNumberRows()):
             self.TaskList.append(self.TasksTable.GetValueByName(row, "Name"))
 
     def RefreshVariableList(self):
@@ -474,14 +474,14 @@
                 return
 
             tasklist = [name for name in self.TaskList if name != ""]
-            for i in xrange(self.TasksTable.GetNumberRows()):
+            for i in range(self.TasksTable.GetNumberRows()):
                 task = self.TasksTable.GetValueByName(i, "Name")
                 if task in tasklist:
                     tasklist.remove(task)
             if len(tasklist) > 0:
                 old_name = tasklist[0].upper()
                 new_name = self.TasksTable.GetValue(row, col)
-                for i in xrange(self.InstancesTable.GetNumberRows()):
+                for i in range(self.InstancesTable.GetNumberRows()):
                     name = self.InstancesTable.GetValueByName(i, "Task").upper()
                     if old_name == name:
                         self.InstancesTable.SetValueByName(i, "Task", new_name)
--- a/editors/SFCViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/SFCViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 
 import wx
 
--- a/editors/TextViewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/TextViewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import re
 from functools import reduce
 
@@ -43,17 +43,17 @@
 
 
 NEWLINE = "\n"
-NUMBERS = [str(i) for i in xrange(10)]
+NUMBERS = [str(i) for i in range(10)]
 LETTERS = ['_']
-for i in xrange(26):
+for i in range(26):
     LETTERS.append(chr(ord('a') + i))
     LETTERS.append(chr(ord('A') + i))
 
 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING,
  STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP,
  STC_PLC_ERROR, STC_PLC_SEARCH_RESULT,
- STC_PLC_EMPTY] = range(11)
-[SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT, PRAGMA, DPRAGMA] = range(8)
+ STC_PLC_EMPTY] = list(range(11))
+[SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT, PRAGMA, DPRAGMA] = list(range(8))
 
 re_texts = {}
 re_texts["letter"] = "[A-Za-z]"
@@ -70,7 +70,7 @@
 
 
 def LineStartswith(line, symbols):
-    return reduce(lambda x, y: x or y, map(line.startswith, symbols), False)
+    return reduce(lambda x, y: x or y, list(map(line.startswith, symbols)), False)
 
 
 class TextViewer(EditorPanel):
@@ -496,7 +496,7 @@
             for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
                 for blocktype in category["list"]:
                     blockname = blocktype["name"].upper()
-                    if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in self.Variables.keys():
+                    if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in list(self.Variables.keys()):
                         interface = dict([(name, {}) for name, _type, _modifier in blocktype["inputs"] + blocktype["outputs"] if name != ''])
                         for param in ["EN", "ENO"]:
                             if param not in interface:
@@ -899,9 +899,9 @@
                         elif words[0].upper() in ["JMP", "JMPC", "JMPNC"]:
                             kw = self.Jumps
                         else:
-                            kw = self.Variables.keys()
-                else:
-                    kw = self.Keywords + self.Variables.keys() + self.Functions.keys()
+                            kw = list(self.Variables.keys())
+                else:
+                    kw = self.Keywords + list(self.Variables.keys()) + list(self.Functions.keys())
                 if len(kw) > 0:
                     if len(words[-1]) > 0:
                         kw = [keyword for keyword in kw if keyword.startswith(words[-1])]
--- a/editors/Viewer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/editors/Viewer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import math
 from time import time as gettime
 from threading import Lock
@@ -88,7 +88,7 @@
     MAX_ZOOMIN = 4
 else:
     MAX_ZOOMIN = 7
-ZOOM_FACTORS = [math.sqrt(2) ** x for x in xrange(-6, MAX_ZOOMIN)]
+ZOOM_FACTORS = [math.sqrt(2) ** x for x in range(-6, MAX_ZOOMIN)]
 
 
 WX_NO_LOGICAL = "gtk3" in wx.PlatformInfo
@@ -481,7 +481,7 @@
         dc = self.Parent.GetLogicalDC()
         ipw, _iph = dc.GetTextExtent(self.GetInstanceName())
         vw, vh = 0, 0
-        for value in self.VALUE_TRANSLATION.itervalues():
+        for value in self.VALUE_TRANSLATION.values():
             w, h = dc.GetTextExtent(" (%s)" % value)
             vw = max(vw, w)
             vh = max(vh, h)
@@ -526,10 +526,10 @@
 
     # Add Block Pin Menu items to the given menu
     def AddBlockPinMenuItems(self, menu, connector):
-        no_modifier = self.AppendItem(menu,  _(u'No modifier'), self.OnNoModifierMenu, kind=wx.ITEM_RADIO)
-        negated = self.AppendItem(menu,  _(u'Negated'), self.OnNegatedMenu, kind=wx.ITEM_RADIO)
-        rising_edge = self.AppendItem(menu,  _(u'Rising Edge'), self.OnRisingEdgeMenu, kind=wx.ITEM_RADIO)
-        falling_edge = self.AppendItem(menu,  _(u'Falling Edge'), self.OnFallingEdgeMenu, kind=wx.ITEM_RADIO)
+        no_modifier = self.AppendItem(menu,  _('No modifier'), self.OnNoModifierMenu, kind=wx.ITEM_RADIO)
+        negated = self.AppendItem(menu,  _('Negated'), self.OnNegatedMenu, kind=wx.ITEM_RADIO)
+        rising_edge = self.AppendItem(menu,  _('Rising Edge'), self.OnRisingEdgeMenu, kind=wx.ITEM_RADIO)
+        falling_edge = self.AppendItem(menu,  _('Falling Edge'), self.OnFallingEdgeMenu, kind=wx.ITEM_RADIO)
 
         not_a_function = self.Controler.GetEditedElementType(
             self.TagName, self.Debug) != "function"
@@ -547,20 +547,20 @@
 
     # Add Alignment Menu items to the given menu
     def AddAlignmentMenuItems(self, menu):
-        self.AppendItem(menu, _(u'Left'), self.OnAlignLeftMenu)
-        self.AppendItem(menu, _(u'Center'), self.OnAlignCenterMenu)
-        self.AppendItem(menu, _(u'Right'), self.OnAlignRightMenu)
+        self.AppendItem(menu, _('Left'), self.OnAlignLeftMenu)
+        self.AppendItem(menu, _('Center'), self.OnAlignCenterMenu)
+        self.AppendItem(menu, _('Right'), self.OnAlignRightMenu)
         menu.AppendSeparator()
-        self.AppendItem(menu, _(u'Top'), self.OnAlignTopMenu)
-        self.AppendItem(menu, _(u'Middle'), self.OnAlignMiddleMenu)
-        self.AppendItem(menu, _(u'Bottom'), self.OnAlignBottomMenu)
+        self.AppendItem(menu, _('Top'), self.OnAlignTopMenu)
+        self.AppendItem(menu, _('Middle'), self.OnAlignMiddleMenu)
+        self.AppendItem(menu, _('Bottom'), self.OnAlignBottomMenu)
 
     # Add Wire Menu items to the given menu
     def AddWireMenuItems(self, menu, delete=False, replace=False):
-        self.AppendItem(menu, _(u'Add Wire Segment'), self.OnAddSegmentMenu)
-        delete_segment = self.AppendItem(menu, _(u'Delete Wire Segment'),
+        self.AppendItem(menu, _('Add Wire Segment'), self.OnAddSegmentMenu)
+        delete_segment = self.AppendItem(menu, _('Delete Wire Segment'),
                                          self.OnDeleteSegmentMenu)
-        replace_wire = self.AppendItem(menu, _(u'Replace Wire by connections'),
+        replace_wire = self.AppendItem(menu, _('Replace Wire by connections'),
                                        self.OnReplaceWireMenu)
 
         delete_segment.Enable(delete)
@@ -568,81 +568,81 @@
 
     # Add Divergence Menu items to the given menu
     def AddDivergenceMenuItems(self, menu, delete=False):
-        self.AppendItem(menu, _(u'Add Divergence Branch'),
+        self.AppendItem(menu, _('Add Divergence Branch'),
                         self.OnAddBranchMenu)
-        delete_branch = self.AppendItem(menu, _(u'Delete Divergence Branch'),
+        delete_branch = self.AppendItem(menu, _('Delete Divergence Branch'),
                                         self.OnDeleteBranchMenu)
 
         delete_branch.Enable(delete)
 
     # Add Add Menu items to the given menu
     def AddAddMenuItems(self, menu):
-        self.AppendItem(menu, _(u'Block'),
+        self.AppendItem(menu, _('Block'),
                         self.GetAddMenuCallBack(self.AddNewBlock))
-        self.AppendItem(menu, _(u'Variable'),
+        self.AppendItem(menu, _('Variable'),
                         self.GetAddMenuCallBack(self.AddNewVariable))
-        self.AppendItem(menu, _(u'Connection'),
+        self.AppendItem(menu, _('Connection'),
                         self.GetAddMenuCallBack(self.AddNewConnection))
         menu.AppendSeparator()
 
         if self.CurrentLanguage != "FBD":
-            self.AppendItem(menu, _(u'Power Rail'),
+            self.AppendItem(menu, _('Power Rail'),
                             self.GetAddMenuCallBack(self.AddNewPowerRail))
-            self.AppendItem(menu, _(u'Contact'),
+            self.AppendItem(menu, _('Contact'),
                             self.GetAddMenuCallBack(self.AddNewContact))
 
             if self.CurrentLanguage != "SFC":
-                self.AppendItem(menu, _(u'Coil'),
+                self.AppendItem(menu, _('Coil'),
                                 self.GetAddMenuCallBack(self.AddNewCoil))
 
             menu.AppendSeparator()
 
         if self.CurrentLanguage == "SFC":
-            self.AppendItem(menu, _(u'Initial Step'),
+            self.AppendItem(menu, _('Initial Step'),
                             self.GetAddMenuCallBack(self.AddNewStep, True))
-            self.AppendItem(menu, (u'Step'),
+            self.AppendItem(menu, ('Step'),
                             self.GetAddMenuCallBack(self.AddNewStep))
-            self.AppendItem(menu, (u'Transition'),
+            self.AppendItem(menu, ('Transition'),
                             self.GetAddMenuCallBack(self.AddNewTransition))
-            self.AppendItem(menu, (u'Action Block'),
+            self.AppendItem(menu, ('Action Block'),
                             self.GetAddMenuCallBack(self.AddNewActionBlock))
-            self.AppendItem(menu, (u'Divergence'),
+            self.AppendItem(menu, ('Divergence'),
                             self.GetAddMenuCallBack(self.AddNewDivergence))
-            self.AppendItem(menu, (u'Jump'),
+            self.AppendItem(menu, ('Jump'),
                             self.GetAddMenuCallBack(self.AddNewJump))
             menu.AppendSeparator()
 
-        self.AppendItem(menu, _(u'Comment'),
+        self.AppendItem(menu, _('Comment'),
                         self.GetAddMenuCallBack(self.AddNewComment))
 
     # Add Default Menu items to the given menu
     def AddDefaultMenuItems(self, menu, edit=False, block=False):
         if block:
-            edit_block = self.AppendItem(menu, _(u'Edit Block'),
+            edit_block = self.AppendItem(menu, _('Edit Block'),
                                          self.OnEditBlockMenu)
-            self.AppendItem(menu, _(u'Adjust Block Size'),
+            self.AppendItem(menu, _('Adjust Block Size'),
                             self.OnAdjustBlockSizeMenu)
-            self.AppendItem(menu, _(u'Delete'), self.OnDeleteMenu)
+            self.AppendItem(menu, _('Delete'), self.OnDeleteMenu)
 
             edit_block.Enable(edit)
 
         else:
             if self.CurrentLanguage == 'FBD':
-                self.AppendItem(menu, _(u'Clear Execution Order'),
+                self.AppendItem(menu, _('Clear Execution Order'),
                                 self.OnClearExecutionOrderMenu)
-                self.AppendItem(menu, _(u'Reset Execution Order'),
+                self.AppendItem(menu, _('Reset Execution Order'),
                                 self.OnResetExecutionOrderMenu)
                 menu.AppendSeparator()
 
             add_menu = wx.Menu(title='')
             self.AddAddMenuItems(add_menu)
-            menu.AppendMenu(-1, _(u'Add'), add_menu)
+            menu.AppendMenu(-1, _('Add'), add_menu)
 
         menu.AppendSeparator()
 
-        cut = self.AppendItem(menu, _(u'Cut'), self.GetClipboardCallBack(self.Cut))
-        copy = self.AppendItem(menu, _(u'Copy'), self.GetClipboardCallBack(self.Copy))
-        paste = self.AppendItem(menu, _(u'Paste'), self.GetAddMenuCallBack(self.Paste))
+        cut = self.AppendItem(menu, _('Cut'), self.GetClipboardCallBack(self.Cut))
+        copy = self.AppendItem(menu, _('Copy'), self.GetClipboardCallBack(self.Copy))
+        paste = self.AppendItem(menu, _('Paste'), self.GetAddMenuCallBack(self.Paste))
 
         cut.Enable(block)
         copy.Enable(block)
@@ -920,9 +920,9 @@
         self.Comments.pop(comment.GetId())
 
     def GetElements(self, sort_blocks=False, sort_wires=False, sort_comments=False):
-        blocks = self.Blocks.values()
-        wires = self.Wires.keys()
-        comments = self.Comments.values()
+        blocks = list(self.Blocks.values())
+        wires = list(self.Wires.keys())
+        comments = list(self.Comments.values())
         if sort_blocks:
             blocks.sort(lambda x, y: cmp(x.GetId(), y.GetId()))
         if sort_wires:
@@ -933,7 +933,7 @@
 
     def GetContinuationByName(self, name):
         blocks = []
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             if isinstance(block, FBD_Connector) and\
                block.GetType() == CONTINUATION and\
                block.GetName() == name:
@@ -941,7 +941,7 @@
         return blocks
 
     def GetConnectorByName(self, name):
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             if isinstance(block, FBD_Connector) and\
                block.GetType() == CONNECTOR and\
                block.GetName() == name:
@@ -957,11 +957,11 @@
         width, height = self.Editor.GetClientSize()
         screen = wx.Rect(int(x / self.ViewScale[0]), int(y / self.ViewScale[1]),
                          int(width / self.ViewScale[0]), int(height / self.ViewScale[1]))
-        for comment in self.Comments.itervalues():
+        for comment in self.Comments.values():
             comment.TestVisible(screen)
-        for wire in self.Wires.iterkeys():
+        for wire in self.Wires.keys():
             wire.TestVisible(screen)
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             block.TestVisible(screen)
 
     def GetElementIECPath(self, element):
@@ -1042,12 +1042,12 @@
 
     def Flush(self):
         self.UnsubscribeAllDataConsumers(tick=False)
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             block.Flush()
 
     # Remove all elements
     def CleanView(self):
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             block.Clean()
         self.ResetView()
 
@@ -1137,7 +1137,7 @@
             self.GridBrush = wx.TRANSPARENT_BRUSH
         page_size = properties["pageSize"]
         if page_size != (0, 0):
-            self.PageSize = map(int, page_size)
+            self.PageSize = list(map(int, page_size))
             self.PagePen = MiterPen(wx.Colour(180, 180, 180))
         else:
             self.PageSize = None
@@ -1219,7 +1219,7 @@
                     wire.SetModifier(self.GetWireModifier(wire))
 
         if self.Debug:
-            for block in self.Blocks.itervalues():
+            for block in self.Blocks.values():
                 block.SpreadCurrent()
                 if isinstance(block, FBD_Block):
                     for output_connector in block.GetConnectors()["outputs"]:
@@ -1479,7 +1479,7 @@
     def FindBlock(self, event):
         dc = self.GetLogicalDC()
         pos = event.GetLogicalPosition(dc)
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             if block.HitTest(pos) or block.TestHandle(event) != (0, 0):
                 return block
         return None
@@ -1510,7 +1510,7 @@
     def FindBlockConnectorWithError(self, pos, direction=None, exclude=None):
         error = False
         startblock = None
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             connector = block.TestConnector(pos, direction, exclude)
             if connector:
                 if self.IsWire(self.SelectedElement):
@@ -1670,7 +1670,7 @@
         menu = wx.Menu(title='')
         align_menu = wx.Menu(title='')
         self.AddAlignmentMenuItems(align_menu)
-        menu.AppendMenu(-1, _(u'Alignment'), align_menu)
+        menu.AppendMenu(-1, _('Alignment'), align_menu)
         menu.AppendSeparator()
         self.AddDefaultMenuItems(menu, block=True)
         self.Editor.PopupMenu(menu)
@@ -1999,10 +1999,10 @@
                         NORTH: [NORTH, SOUTH],
                         SOUTH: [SOUTH, NORTH]}[connector.GetDirection()]
                     wire = Wire(self,
-                                *map(list, zip(
+                                *list(map(list, list(zip(
                                     [wx.Point(pos.x, pos.y),
                                      wx.Point(scaled_pos.x, scaled_pos.y)],
-                                    directions)))
+                                    directions)))))
                     wire.oldPos = scaled_pos
                     wire.Handle = (HANDLE_POINT, 0)
                     wire.ProcessDragging(0, 0, event, None)
@@ -2372,10 +2372,10 @@
             poss_div_types = []
 
             SFC_WireMenu_Buttons = {
-                'SFC_Step': (_(u'Step'), self.GetAddToWireMenuCallBack(self.AddNewStep, False)),
-                'SFC_Jump': (_(u'Jump'), self.GetAddToWireMenuCallBack(self.AddNewJump)),
-                'SFC_Transition': (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, False)),
-                'SFC_ActionBlock': (_(u'Action Block'), self.GetAddToWireMenuCallBack(self.AddNewActionBlock))}
+                'SFC_Step': (_('Step'), self.GetAddToWireMenuCallBack(self.AddNewStep, False)),
+                'SFC_Jump': (_('Jump'), self.GetAddToWireMenuCallBack(self.AddNewJump)),
+                'SFC_Transition': (_('Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, False)),
+                'SFC_ActionBlock': (_('Action Block'), self.GetAddToWireMenuCallBack(self.AddNewActionBlock))}
 
             for endblock in self.SFC_StandardRules.get(startblockname):
                 if start_direction in endblock:
@@ -2384,27 +2384,27 @@
                     else:
                         items.append(SFC_WireMenu_Buttons[endblock[0]])
             if len(poss_div_types) > 0:
-                items.append((_(u'Divergence'), self.GetAddToWireMenuCallBack(self.AddNewDivergence,
+                items.append((_('Divergence'), self.GetAddToWireMenuCallBack(self.AddNewDivergence,
                                                                               poss_div_types)))
         elif start_direction == EAST:
             items.extend([
-                (_(u'Block'), self.GetAddToWireMenuCallBack(self.AddNewBlock)),
-                (_(u'Connection'), self.GetAddToWireMenuCallBack(self.AddNewConnection))])
+                (_('Block'), self.GetAddToWireMenuCallBack(self.AddNewBlock)),
+                (_('Connection'), self.GetAddToWireMenuCallBack(self.AddNewConnection))])
 
             if self.CurrentLanguage != "FBD":
-                items.append((_(u'Contact'), self.GetAddToWireMenuCallBack(self.AddNewContact)))
+                items.append((_('Contact'), self.GetAddToWireMenuCallBack(self.AddNewContact)))
 
             if self.CurrentLanguage == "LD":
                 items.extend([
-                    (_(u'Coil'), self.GetAddToWireMenuCallBack(self.AddNewCoil)),
-                    (_(u'Power Rail'), self.GetAddToWireMenuCallBack(self.AddNewPowerRail))])
+                    (_('Coil'), self.GetAddToWireMenuCallBack(self.AddNewCoil)),
+                    (_('Power Rail'), self.GetAddToWireMenuCallBack(self.AddNewPowerRail))])
 
             if self.CurrentLanguage == "SFC":
                 items.append(
-                    (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, True)))
+                    (_('Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, True)))
             else:
                 items.append(
-                    (_(u'Variable'), self.GetAddToWireMenuCallBack(self.AddNewVariable, True)))
+                    (_('Variable'), self.GetAddToWireMenuCallBack(self.AddNewVariable, True)))
         return items
 
     # -------------------------------------------------------------------------------
@@ -2732,7 +2732,7 @@
 
     def AddNewJump(self, bbox, wire=None):
         choices = []
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             if isinstance(block, SFC_Step):
                 choices.append(block.GetName())
         dialog = wx.SingleChoiceDialog(self.ParentWindow,
@@ -2947,7 +2947,7 @@
             if self.GetDrawingMode() == DRIVENDRAWING_MODE:
                 old_name = step.GetName().upper()
                 if new_name.upper() != old_name:
-                    for block in self.Blocks.itervalues():
+                    for block in self.Blocks.values():
                         if isinstance(block, SFC_Jump):
                             if old_name == block.GetTarget().upper():
                                 block.SetTarget(new_name)
@@ -3000,7 +3000,7 @@
 
     def EditJumpContent(self, jump):
         choices = []
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             if isinstance(block, SFC_Step):
                 choices.append(block.GetName())
         dialog = wx.SingleChoiceDialog(self.ParentWindow,
@@ -3314,7 +3314,7 @@
         if self.GetDrawingMode() == DRIVENDRAWING_MODE:
             name = step.GetName().upper()
             remove_jumps = []
-            for block in self.Blocks.itervalues():
+            for block in self.Blocks.values():
                 if isinstance(block, SFC_Jump):
                     if name == block.GetTarget().upper():
                         remove_jumps.append(block)
@@ -3658,27 +3658,27 @@
             xstart, ystart = self.GetViewStart()
             window_size = self.Editor.GetClientSize()
             if self.PageSize[0] != 0:
-                for x in xrange(self.PageSize[0] - (xstart * SCROLLBAR_UNIT) % self.PageSize[0], int(window_size[0] / self.ViewScale[0]), self.PageSize[0]):
+                for x in range(self.PageSize[0] - (xstart * SCROLLBAR_UNIT) % self.PageSize[0], int(window_size[0] / self.ViewScale[0]), self.PageSize[0]):
                     dc.DrawLine(xstart * SCROLLBAR_UNIT + x + 1, int(ystart * SCROLLBAR_UNIT / self.ViewScale[0]),
                                 xstart * SCROLLBAR_UNIT + x + 1, int((ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[0]))
             if self.PageSize[1] != 0:
-                for y in xrange(self.PageSize[1] - (ystart * SCROLLBAR_UNIT) % self.PageSize[1], int(window_size[1] / self.ViewScale[1]), self.PageSize[1]):
+                for y in range(self.PageSize[1] - (ystart * SCROLLBAR_UNIT) % self.PageSize[1], int(window_size[1] / self.ViewScale[1]), self.PageSize[1]):
                     dc.DrawLine(int(xstart * SCROLLBAR_UNIT / self.ViewScale[0]), ystart * SCROLLBAR_UNIT + y + 1,
                                 int((xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[1]), ystart * SCROLLBAR_UNIT + y + 1)
 
         # Draw all elements
-        for comment in self.Comments.itervalues():
+        for comment in self.Comments.values():
             if comment != self.SelectedElement and (comment.IsVisible() or printing):
                 comment.Draw(dc)
-        for wire in self.Wires.iterkeys():
+        for wire in self.Wires.keys():
             if wire != self.SelectedElement and (wire.IsVisible() or printing):
                 if not self.Debug or not wire.GetValue():
                     wire.Draw(dc)
         if self.Debug:
-            for wire in self.Wires.iterkeys():
+            for wire in self.Wires.keys():
                 if wire != self.SelectedElement and (wire.IsVisible() or printing) and wire.GetValue():
                     wire.Draw(dc)
-        for block in self.Blocks.itervalues():
+        for block in self.Blocks.values():
             if block != self.SelectedElement and (block.IsVisible() or printing):
                 block.Draw(dc)
 
--- a/etherlab/ConfigEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/etherlab/ConfigEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -9,8 +9,8 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import os
 import re
 
@@ -30,7 +30,7 @@
 from etherlab.EtherCATManagementEditor import EtherCATManagementTreebook, MasterStatePanelClass
 # -----------------------------------------------------------------------
 
-[ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE] = range(3)
+[ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE] = list(range(3))
 
 
 def GetVariablesTableColnames(position=False):
@@ -421,7 +421,7 @@
             if values[1] == "location":
                 result = LOCATION_MODEL.match(values[0])
                 if result is not None:
-                    location = map(int, result.group(1).split('.'))
+                    location = list(map(int, result.group(1).split('.')))
                 master_location = self.ParentWindow.GetMasterLocation()
                 if master_location == tuple(location[:len(master_location)]) and \
                    len(location) - len(master_location) == 3:
@@ -485,7 +485,7 @@
             if values[1] == "location":
                 result = LOCATION_MODEL.match(values[0])
                 if result is not None and len(values) > 5:
-                    location = map(int, result.group(1).split('.'))
+                    location = list(map(int, result.group(1).split('.')))
                     access = values[5]
             elif values[1] == "variable":
                 location = values[0]
--- a/etherlab/EtherCATManagementEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/etherlab/EtherCATManagementEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -7,8 +7,8 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import os
 import string
 from xml.dom import minidom
@@ -331,7 +331,7 @@
         wx.Panel.__init__(self, parent, -1)
 
         self.DatatypeDescription, self.CommunicationObject, self.ManufacturerSpecific, \
-            self.ProfileSpecific, self.Reserved, self.AllSDOData = range(6)
+            self.ProfileSpecific, self.Reserved, self.AllSDOData = list(range(6))
 
         self.Controler = controler
 
@@ -418,7 +418,7 @@
         If the off is selected, the monitor thread gets off.
         @param event: wx.EVT_RADIOBOX object 
         """
-        on, off = range(2)
+        on, off = list(range(2))
 
         if event.GetInt() == on:
             CheckThreadFlag = self.SDOMonitoringThreadOn()
@@ -455,7 +455,7 @@
     def SDOMonitorThreadProc(self):
         while self.SDOMonitoringFlag and self.Controler.GetCTRoot()._connector.PLCStatus != "Started":
             self.SDOValuesList = self.Controler.GetCTRoot()._connector.GetSDOData()
-            LocalData = self.SDOValuesList[0].items()
+            LocalData = list(self.SDOValuesList[0].items())
             LocalData.sort()
             if self.SDOValuesList[1] != self.Controler.GetSlavePos():
                 continue
@@ -508,7 +508,7 @@
         Parse SDO data set that obtain "ESI file"
         @param entries: SDO entry list 
         """  
-        entries_list = entries.items()
+        entries_list = list(entries.items())
         entries_list.sort()
         self.ForDefaultValueFlag = False
         self.CompareValue = ""
@@ -518,7 +518,7 @@
             # exclude entry that isn't in the objects
             check_mapping = entry["PDOMapping"]
             if check_mapping is "T" or check_mapping is "R":
-                if "PDO index" not in entry.keys():
+                if "PDO index" not in list(entry.keys()):
                     continue
 
             idx = "0" + entry["Index"].strip("#")
@@ -793,7 +793,7 @@
             SDOPanel.SDOMonitorGrid.AppendRows(len(SDOPanel.SDOMonitorEntries))
             SDOPanel.SetSDOTraceValues(SDOPanel.SDOMonitorEntries)
             
-            SME_list = SDOPanel.SDOMonitorEntries.items()
+            SME_list = list(SDOPanel.SDOMonitorEntries.items())
             SME_list.sort()
 
             gridRow = 0
@@ -1547,7 +1547,7 @@
         # Config Data: EEPROM Size, PDI Type, Device Emulation
         # Find PDI Type in pdiType dictionary
         cnt_pdi_type = self.Controler.CommonMethod.SmartViewInfosFromXML["pdi_type"]
-        for i in self.PDIType.keys():
+        for i in list(self.PDIType.keys()):
             if cnt_pdi_type == i:
                 cnt_pdi_type = self.PDIType[i][0]
                 break
@@ -1627,7 +1627,7 @@
         eeprom_size = str((int(self.GetWordAddressData(sii_dict.get('Size'), 10))+1)//8*1024)
         # Find PDI Type in pdiType dictionary
         cnt_pdi_type = int(self.GetWordAddressData(sii_dict.get('PDIControl'), 16).split('x')[1][2:4], 16)
-        for i in self.PDIType.keys():
+        for i in list(self.PDIType.keys()):
             if cnt_pdi_type == i:
                 cnt_pdi_type = self.PDIType[i][0]
                 break
@@ -2106,7 +2106,7 @@
                                                   ("pdi", "type", self.PDIType),
                                                   ("fmmu", "number", self.FMMUNumber),
                                                   ("sm", "number", self.SMNumber)]:
-                        if property in register.attributes.keys():
+                        if property in list(register.attributes.keys()):
                             if type == "type":
                                 if register.attributes[property].value == value:
                                     self.GetRegisterInfo(reg_info_tree, register)
@@ -2153,7 +2153,7 @@
                                                       ("pdi", "type", self.PDIType),
                                                       ("fmmu", "number", self.FMMUNumber),
                                                       ("sm", "number", self.SMNumber)]:
-                            if property in detail.attributes.keys():
+                            if property in list(detail.attributes.keys()):
                                 if type == "type":
                                     if detail.attributes[property].value == value:
                                         self.GetRegisterDetailInfo(reg_info_tree, reg_index, detail)
@@ -2522,7 +2522,7 @@
 
         reg_sub_grid_data = []
 
-        BIT_RANGE, NAME, DESCRIPTIONS = range(3)
+        BIT_RANGE, NAME, DESCRIPTIONS = list(range(3))
 
         # Check if this register's detail description is exist or not,
         # and create data structure for the detail description table ; sub grid
@@ -2817,7 +2817,7 @@
         """
         Update the data of the slave information.
         """
-        position, not_used, state, not_used, name = range(5)
+        position, not_used, state, not_used, name = list(range(5))
         
         slave_node = []
         slave_info_list = []
@@ -2933,7 +2933,7 @@
                 ec_idx += 1
             
             # set texts in "error" column. 
-            ec_info_list = error_counter.items()
+            ec_info_list = list(error_counter.items())
             ec_info_list.sort()
             
             err_checker = "none"
--- a/etherlab/EthercatCIA402Slave.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/etherlab/EthercatCIA402Slave.py	Fri Oct 28 12:39:15 2022 +0800
@@ -9,7 +9,7 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import os
 
 import wx
@@ -424,7 +424,7 @@
             if variable in check_variable:
                 continue
 
-            var_infos = dict(zip(["name", "index", "subindex", "var_type", "dir"], variable))
+            var_infos = dict(list(zip(["name", "index", "subindex", "var_type", "dir"], variable)))
             var_infos["location"] = location_str
             var_infos["var_size"] = self.GetSizeOfType(var_infos["var_type"])
             var_infos["var_name"] = "__%(dir)s%(var_size)s%(location)s_%(index)d_%(subindex)d" % var_infos
--- a/etherlab/EthercatMaster.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/etherlab/EthercatMaster.py	Fri Oct 28 12:39:15 2022 +0800
@@ -9,7 +9,7 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import os
 from copy import deepcopy
 from functools import reduce
@@ -298,7 +298,7 @@
                     EtherCATConfigParser.LoadXMLString(config_xmlfile.read())
                 if error is None:
                     config_is_saved = True
-            except Exception, e:
+            except Exception as e:
                 error = e.message
             config_xmlfile.close()
             
@@ -651,7 +651,7 @@
             # Test OD
             entries = device.GetEntriesList(limits)
             #entries = self.CTNParent.GetEntriesList()
-            entries_list = entries.items()
+            entries_list = list(entries.items())
             entries_list.sort()
             entries = []
             current_index = None
@@ -817,7 +817,7 @@
                     else:
                         sync_managers.append(LOCATION_VAR_INPUT)
 
-                entries = device.GetEntriesList().items()
+                entries = list(device.GetEntriesList().items())
                 entries.sort()
                 for (index, subindex), entry in entries:
                     var_size = self.GetSizeOfType(entry["Type"])
--- a/etherlab/EthercatSlave.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/etherlab/EthercatSlave.py	Fri Oct 28 12:39:15 2022 +0800
@@ -9,7 +9,7 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 
 from PLCControler import LOCATION_CONFNODE, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
 from ConfigTreeNode import ConfigTreeNode
--- a/etherlab/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/etherlab/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,4 +1,4 @@
-from __future__ import absolute_import
+
 
 from etherlab.etherlab import *
 from util.BitmapLibrary import AddBitmapFolder
--- a/etherlab/runtime_etherlab.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/etherlab/runtime_etherlab.py	Fri Oct 28 12:39:15 2022 +0800
@@ -9,7 +9,7 @@
 #
 # see copying file for copyrights details.
 
-from __future__ import absolute_import
+
 import os
 import signal
 import subprocess
--- a/graphics/DebugDataConsumer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/graphics/DebugDataConsumer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import datetime
 
 
--- a/graphics/FBD_Objects.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/graphics/FBD_Objects.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import wx
 from six.moves import xrange
 
@@ -78,7 +78,7 @@
         return block
 
     def GetConnectorTranslation(self, element):
-        return dict(zip(self.Inputs + self.Outputs, element.Inputs + element.Outputs))
+        return dict(list(zip(self.Inputs + self.Outputs, element.Inputs + element.Outputs)))
 
     def Flush(self):
         for input in self.Inputs:
@@ -165,7 +165,7 @@
             linesize = max((self.Size[1] - BLOCK_LINE_SIZE) // lines, BLOCK_LINE_SIZE)
             # Update inputs and outputs positions
             position = BLOCK_LINE_SIZE + linesize // 2
-            for i in xrange(lines):
+            for i in range(lines):
                 if scaling is not None:
                     ypos = round_scaling(self.Pos.y + position, scaling[1]) - self.Pos.y
                 else:
@@ -256,7 +256,7 @@
                 outputs = [output for output in blocktype["outputs"]]
                 if blocktype["extensible"]:
                     start = int(inputs[-1][0].replace("IN", ""))
-                    for dummy in xrange(self.Extension - len(blocktype["inputs"])):
+                    for dummy in range(self.Extension - len(blocktype["inputs"])):
                         start += 1
                         inputs.append(("IN%d" % start, inputs[-1][1], inputs[-1][2]))
                 comment = blocktype["comment"]
@@ -451,7 +451,7 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            highlight_items = self.Highlights.items()
+            highlight_items = list(self.Highlights.items())
             for name, highlights in highlight_items:
                 highlights = ClearHighlights(highlights, highlight_type)
                 if len(highlights) == 0:
--- a/graphics/GraphicCommons.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/graphics/GraphicCommons.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from math import *
 from future.builtins import round
 from six import string_types
@@ -68,15 +68,15 @@
 SFC_ACTION_MIN_SIZE = (100, 30)         # Minimum size of an action block line
 
 # Type definition constants for graphic elements
-[INPUT, OUTPUT, INOUT] = range(3)
-[CONNECTOR, CONTINUATION] = range(2)
-[LEFTRAIL, RIGHTRAIL] = range(2)
-[CONTACT_NORMAL, CONTACT_REVERSE, CONTACT_RISING, CONTACT_FALLING] = range(4)
-[COIL_NORMAL, COIL_REVERSE, COIL_SET, COIL_RESET, COIL_RISING, COIL_FALLING] = range(6)
-[SELECTION_DIVERGENCE, SELECTION_CONVERGENCE, SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE] = range(4)
+[INPUT, OUTPUT, INOUT] = list(range(3))
+[CONNECTOR, CONTINUATION] = list(range(2))
+[LEFTRAIL, RIGHTRAIL] = list(range(2))
+[CONTACT_NORMAL, CONTACT_REVERSE, CONTACT_RISING, CONTACT_FALLING] = list(range(4))
+[COIL_NORMAL, COIL_REVERSE, COIL_SET, COIL_RESET, COIL_RISING, COIL_FALLING] = list(range(6))
+[SELECTION_DIVERGENCE, SELECTION_CONVERGENCE, SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE] = list(range(4))
 
 # Constants for defining the type of dragging that has been selected
-[HANDLE_MOVE, HANDLE_RESIZE, HANDLE_POINT, HANDLE_SEGMENT, HANDLE_CONNECTOR] = range(5)
+[HANDLE_MOVE, HANDLE_RESIZE, HANDLE_POINT, HANDLE_SEGMENT, HANDLE_CONNECTOR] = list(range(5))
 
 # List of value for resize handle that are valid
 VALID_HANDLES = [(1, 1), (1, 2), (1, 3), (2, 3), (3, 3), (3, 2), (3, 1), (2, 1)]
@@ -87,10 +87,10 @@
 # Contants for defining which mode is selected for each view
 [MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT,
  MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP,
- MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION, MODE_MOTION] = range(15)
+ MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION, MODE_MOTION] = list(range(15))
 
 # Contants for defining alignment types for graphic group
-[ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM] = range(6)
+[ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM] = list(range(6))
 
 # Contants for defining which drawing mode is selected for app
 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2]
@@ -1918,7 +1918,7 @@
     # Returns if the point given is on one of the wire segments
     def HitTest(self, pt, connectors=True):
         test = False
-        for i in xrange(len(self.Points) - 1):
+        for i in range(len(self.Points) - 1):
             rect = wx.Rect(0, 0, 0, 0)
             if i == 0 and self.StartConnected is not None:
                 x1 = self.Points[i].x - self.Segments[0][0] * CONNECTOR_SIZE
@@ -1953,7 +1953,7 @@
 
     # Returns the wire segment if the point given is on it
     def TestSegment(self, pt, all=False):
-        for i in xrange(len(self.Segments)):
+        for i in range(len(self.Segments)):
             # If wire is not in a Ladder Diagram, first and last segments are excluded
             if all or 0 < i < len(self.Segments) - 1:
                 x1, y1 = self.Points[i].x, self.Points[i].y
@@ -2233,7 +2233,7 @@
         i = 1
         while i < len(points) - 1:
             if points[i] == points[i + 1] and segments[i - 1] == segments[i + 1]:
-                for dummy in xrange(2):
+                for dummy in range(2):
                     points.pop(i)
                     segments.pop(i)
             else:
@@ -2459,7 +2459,7 @@
         handle_type, handle = self.Handle
         if handle_type == HANDLE_SEGMENT:
             segment, _dir = handle
-            for dummy in xrange(2):
+            for dummy in range(2):
                 self.Points.pop(segment)
                 self.Segments.pop(segment)
             self.GeneratePoints()
--- a/graphics/LD_Objects.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/graphics/LD_Objects.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import wx
 from future.builtins import round
 from six.moves import xrange
@@ -73,8 +73,8 @@
         return powerrail
 
     def GetConnectorTranslation(self, element):
-        return dict(zip([connector for connector in self.Connectors],
-                        [connector for connector in element.Connectors]))
+        return dict(list(zip([connector for connector in self.Connectors],
+                        [connector for connector in element.Connectors])))
 
     # Returns the RedrawRect
     def GetRedrawRect(self, movex=0, movey=0):
@@ -238,7 +238,7 @@
             self.Type = type
             self.Clean()
             self.Connectors = []
-            for dummy in xrange(connectors):
+            for dummy in range(connectors):
                 self.AddConnector()
             self.RefreshSize()
 
@@ -255,7 +255,7 @@
                 position = connector.GetRelPosition()
                 self.RealConnectors.append(max(0., min((position.y - self.Extensions[0]) / height, 1.)))
         elif len(self.Connectors) > 1:
-            self.RealConnectors = map(lambda x: x * 1 / (len(self.Connectors) - 1), xrange(len(self.Connectors)))
+            self.RealConnectors = [x * 1 / (len(self.Connectors) - 1) for x in range(len(self.Connectors))]
         else:
             self.RealConnectors = [0.5]
         Graphic_Element.OnLeftDown(self, event, dc, scaling)
@@ -626,7 +626,7 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            highlight_items = self.Highlights.items()
+            highlight_items = list(self.Highlights.items())
             for name, highlights in highlight_items:
                 highlights = ClearHighlights(highlights, highlight_type)
                 if len(highlights) == 0:
@@ -687,7 +687,7 @@
         self.Output.Draw(dc)
 
         if not getattr(dc, "printing", False):
-            for name, highlights in self.Highlights.iteritems():
+            for name, highlights in self.Highlights.items():
                 if name == "reference":
                     DrawHighlightedText(dc, self.Name, highlights, name_pos[0], name_pos[1])
                 elif typetext != "":
@@ -948,7 +948,7 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            highlight_items = self.Highlights.items()
+            highlight_items = list(self.Highlights.items())
             for name, highlights in highlight_items:
                 highlights = ClearHighlights(highlights, highlight_type)
                 if len(highlights) == 0:
@@ -1016,7 +1016,7 @@
         self.Output.Draw(dc)
 
         if not getattr(dc, "printing", False):
-            for name, highlights in self.Highlights.iteritems():
+            for name, highlights in self.Highlights.items():
                 if name == "reference":
                     DrawHighlightedText(dc, self.Name, highlights, name_pos[0], name_pos[1])
                 elif typetext != "":
--- a/graphics/RubberBand.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/graphics/RubberBand.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from graphics.GraphicCommons import GetScaledEventPosition
--- a/graphics/SFC_Objects.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/graphics/SFC_Objects.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from future.builtins import round
 
 import wx
@@ -976,7 +976,7 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            highlight_items = self.Highlights.items()
+            highlight_items = list(self.Highlights.items())
             for name, highlights in highlight_items:
                 highlights = ClearHighlights(highlights, highlight_type)
                 if len(highlights) == 0:
@@ -1037,7 +1037,7 @@
             self.Condition.Draw(dc)
 
         if not getattr(dc, "printing", False):
-            for name, highlights in self.Highlights.iteritems():
+            for name, highlights in self.Highlights.items():
                 if name == "priority":
                     DrawHighlightedText(dc, str(self.Priority), highlights, priority_pos[0], priority_pos[1])
                 else:
@@ -1067,11 +1067,11 @@
         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
             self.Inputs = [Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH, onlyone=True)]
             self.Outputs = []
-            for i in xrange(number):
+            for i in range(number):
                 self.Outputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone=True))
         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
             self.Inputs = []
-            for i in xrange(number):
+            for i in range(number):
                 self.Inputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, 0), NORTH, onlyone=True))
             self.Outputs = [Connector(self, "", None, wx.Point(self.Size[0] // 2, self.Size[1]), SOUTH, onlyone=True)]
         self.Value = None
@@ -1124,7 +1124,7 @@
         return divergence
 
     def GetConnectorTranslation(self, element):
-        return dict(zip(self.Inputs + self.Outputs, element.Inputs + element.Outputs))
+        return dict(list(zip(self.Inputs + self.Outputs, element.Inputs + element.Outputs)))
 
     # Returns the RedrawRect
     def GetRedrawRect(self, movex=0, movey=0):
@@ -2004,9 +2004,9 @@
         if highlight_type is None:
             self.Highlights = {}
         else:
-            highlight_items = self.Highlights.items()
+            highlight_items = list(self.Highlights.items())
             for number, action_highlights in highlight_items:
-                action_highlight_items = action_highlights.items()
+                action_highlight_items = list(action_highlights.items())
                 for name, attribute_highlights in action_highlight_items:
                     attribute_highlights = ClearHighlights(attribute_highlights, highlight_type)
                     if len(attribute_highlights) == 0:
@@ -2058,7 +2058,7 @@
 
             if not getattr(dc, "printing", False):
                 action_highlights = self.Highlights.get(i, {})
-                for name, attribute_highlights in action_highlights.iteritems():
+                for name, attribute_highlights in action_highlights.items():
                     if name == "qualifier":
                         DrawHighlightedText(dc, action.qualifier, attribute_highlights, qualifier_pos[0], qualifier_pos[1])
                     elif name == "duration":
--- a/graphics/ToolTipProducer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/graphics/ToolTipProducer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import wx
 
 from controls.CustomToolTip import CustomToolTip, TOOLTIP_WAIT_PERIOD
--- a/i18n/mki18n.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/i18n/mki18n.py	Fri Oct 28 12:39:15 2022 +0800
@@ -79,8 +79,8 @@
 # -------------
 #
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import sys
 import re
@@ -229,7 +229,7 @@
 
     languageDict = getSupportedLanguageDict(applicationName)
 
-    for langCode in languageDict.keys():
+    for langCode in list(languageDict.keys()):
         if langCode == 'en':
             pass
         else:
@@ -254,7 +254,7 @@
 
     languageDict = getSupportedLanguageDict(applicationName)
 
-    for langCode in languageDict.keys():
+    for langCode in list(languageDict.keys()):
         if langCode == 'en':
             pass
         else:
@@ -308,7 +308,7 @@
 
     languageDict = getSupportedLanguageDict(applicationName)
 
-    for langCode in languageDict.keys():
+    for langCode in list(languageDict.keys()):
         if (langCode == 'en') and (forceEnglish == 0):
             pass
         else:
@@ -414,7 +414,7 @@
     # translate the path separators
     directory = unixpath(directory)
     # build a list of all directory elements
-    aList = filter(lambda x: len(x) > 0, directory.split('/'))
+    aList = [x for x in directory.split('/') if len(x) > 0]
     theLen = len(aList)
     # if the first element is a Windows-style disk drive
     # concatenate it with the first directory
--- a/modbus/mb_utils.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/modbus/mb_utils.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,8 +22,8 @@
 # This code is made available on the understanding that it will not be
 # used in safety-critical situations without a full and competent review.
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 from six.moves import xrange
 
 # dictionary implementing:
@@ -48,7 +48,7 @@
 
 # Configuration tree value acces helper, for multiple values
 def GetCTVals(child, indexes):
-    return map(lambda index: GetCTVal(child, index), indexes)
+    return [GetCTVal(child, index) for index in indexes]
 
 
 def GetTCPServerNodePrinted(self, child):
@@ -60,7 +60,7 @@
 {"%(locnodestr)s", "%(config_name)s", "%(host)s", "%(port)s", %(slaveid)s, {naf_tcp, {.tcp = {NULL, NULL, DEF_CLOSE_ON_SILENCE}}}, -1 /* mb_nd */, 0 /* init_state */}'''
 
     location = ".".join(map(str, child.GetCurrentLocation()))
-    config_name, host, port, slaveid = GetCTVals(child, range(4))
+    config_name, host, port, slaveid = GetCTVals(child, list(range(4)))
     if host == "#ANY#":
         host = ''
     # slaveid = GetCTVal(child, 2)
@@ -90,16 +90,16 @@
     request_dict["locreqstr"] = "_".join(map(str, child.GetCurrentLocation()))
     request_dict["nodeid"] = str(nodeid)
     request_dict["address"] = GetCTVal(child, 2)
-    if int(request_dict["address"]) not in xrange(65536):
+    if int(request_dict["address"]) not in range(65536):
         self.GetCTRoot().logger.write_error(
             "Modbus plugin: Invalid Start Address in server memory area node %(locreqstr)s (Must be in the range [0..65535])\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
         return None
     request_dict["count"] = GetCTVal(child, 1)
-    if int(request_dict["count"]) not in xrange(1, 65537):
+    if int(request_dict["count"]) not in range(1, 65537):
         self.GetCTRoot().logger.write_error(
             "Modbus plugin: Invalid number of channels in server memory area node %(locreqstr)s (Must be in the range [1..65536-start_address])\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
         return None
-    if (int(request_dict["address"]) + int(request_dict["count"])) not in xrange(1, 65537):
+    if (int(request_dict["address"]) + int(request_dict["count"])) not in range(1, 65537):
         self.GetCTRoot().logger.write_error(
             "Modbus plugin: Invalid number of channels in server memory area node %(locreqstr)s (Must be in the range [1..65536-start_address])\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
         return None
@@ -122,7 +122,7 @@
 {"%(locnodestr)s", "%(config_name)s", "%(device)s", "",%(slaveid)s, {naf_rtu, {.rtu = {NULL, %(baud)s /*baud*/, %(parity)s /*parity*/, 8 /*data bits*/, %(stopbits)s, 0 /* ignore echo */}}}, -1 /* mb_nd */, 0 /* init_state */}'''
 
     location = ".".join(map(str, child.GetCurrentLocation()))
-    config_name, device, baud, parity, stopbits, slaveid = GetCTVals(child, range(6))
+    config_name, device, baud, parity, stopbits, slaveid = GetCTVals(child, list(range(6)))
 
     node_dict = {"locnodestr": location,
                  "config_name": config_name,
@@ -143,7 +143,7 @@
 {"%(locnodestr)s", "%(config_name)s", "%(device)s", "", {naf_rtu, {.rtu = {NULL, %(baud)s /*baud*/, %(parity)s /*parity*/, 8 /*data bits*/, %(stopbits)s, 0 /* ignore echo */}}}, -1 /* mb_nd */, 0 /* init_state */, %(coms_period)s /* communication period  (ms)*/, %(coms_delay)s /* inter request delay (ms)*/, 0 /* prev_error */}'''
 
     location = ".".join(map(str, child.GetCurrentLocation()))
-    config_name, device, baud, parity, stopbits, coms_period, coms_delay = GetCTVals(child, range(7))
+    config_name, device, baud, parity, stopbits, coms_period, coms_delay = GetCTVals(child, list(range(7)))
 
     node_dict = {"locnodestr": location,
                  "config_name": config_name,
@@ -165,7 +165,7 @@
 {"%(locnodestr)s", "%(config_name)s", "%(host)s", "%(port)s", {naf_tcp, {.tcp = {NULL, NULL, DEF_CLOSE_ON_SILENCE}}}, -1 /* mb_nd */, 0 /* init_state */, %(coms_period)s /* communication period (ms)*/, %(coms_delay)s /* inter request delay (ms)*/, 0 /* prev_error */}'''
 
     location = ".".join(map(str, child.GetCurrentLocation()))
-    config_name, host, port, coms_period, coms_delay = GetCTVals(child, range(5))
+    config_name, host, port, coms_period, coms_delay = GetCTVals(child, list(range(5)))
 
     node_dict = {"locnodestr": location,
                  "config_name": config_name,
@@ -211,19 +211,19 @@
         "iotype": modbus_function_dict[GetCTVal(child, 0)][1],
         "maxcount": modbus_function_dict[GetCTVal(child, 0)][2]}
 
-    if int(request_dict["slaveid"]) not in xrange(256):
+    if int(request_dict["slaveid"]) not in range(256):
         self.GetCTRoot().logger.write_error(
             "Modbus plugin: Invalid slaveID in TCP client request node %(locreqstr)s (Must be in the range [0..255])\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
         return None
-    if int(request_dict["address"]) not in xrange(65536):
+    if int(request_dict["address"]) not in range(65536):
         self.GetCTRoot().logger.write_error(
             "Modbus plugin: Invalid Start Address in TCP client request node %(locreqstr)s (Must be in the range [0..65535])\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
         return None
-    if int(request_dict["count"]) not in xrange(1, 1 + int(request_dict["maxcount"])):
+    if int(request_dict["count"]) not in range(1, 1 + int(request_dict["maxcount"])):
         self.GetCTRoot().logger.write_error(
             "Modbus plugin: Invalid number of channels in TCP client request node %(locreqstr)s (Must be in the range [1..%(maxcount)s])\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
         return None
-    if (int(request_dict["address"]) + int(request_dict["count"])) not in xrange(1, 65537):
+    if (int(request_dict["address"]) + int(request_dict["count"])) not in range(1, 65537):
         self.GetCTRoot().logger.write_error(
             "Modbus plugin: Invalid number of channels in TCP client request node %(locreqstr)s (start_address + nr_channels must be less than 65536)\nModbus plugin: Aborting C code generation for this node\n" % request_dict)
         return None
--- a/modbus/modbus.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/modbus/modbus.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # used in safety-critical situations without a full and competent review.
 
 
-from __future__ import absolute_import
+
 import os
 from six.moves import xrange
 
@@ -94,7 +94,7 @@
             if element["name"] == "ModbusRequest":
                 for child in element["children"]:
                     if child["name"] == "Function":
-                        list = modbus_function_dict.keys()
+                        list = list(modbus_function_dict.keys())
                         list.sort()
                         child["type"] = list
         return infos
@@ -240,7 +240,7 @@
             if element["name"] == "MemoryArea":
                 for child in element["children"]:
                     if child["name"] == "MemoryAreaType":
-                        list = modbus_memtype_dict.keys()
+                        list = list(modbus_memtype_dict.keys())
                         list.sort()
                         child["type"] = list
         return infos
@@ -618,7 +618,7 @@
                     if child["name"] == "Stop_Bits":
                         child["type"] = modbus_serial_stopbits_list
                     if child["name"] == "Parity":
-                        child["type"] = modbus_serial_parity_dict.keys()
+                        child["type"] = list(modbus_serial_parity_dict.keys())
         return infos
 
     # Return the number of (modbus library) nodes this specific RTU client will need
@@ -709,7 +709,7 @@
                     if child["name"] == "Stop_Bits":
                         child["type"] = modbus_serial_stopbits_list
                     if child["name"] == "Parity":
-                        child["type"] = modbus_serial_parity_dict.keys()
+                        child["type"] = list(modbus_serial_parity_dict.keys())
         return infos
 
     # Return the number of (modbus library) nodes this specific RTU slave will need
@@ -1026,7 +1026,7 @@
                             start_address = int(GetCTVal(subchild, 2))
                             relative_addr = absloute_address - start_address
                             # test if relative address in request specified range
-                            if relative_addr in xrange(int(GetCTVal(subchild, 1))):
+                            if relative_addr in range(int(GetCTVal(subchild, 1))):
                                 if str(iecvar["NAME"]) not in loc_vars_list:
                                     loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
                                         server_id, memarea, absloute_address))
@@ -1080,7 +1080,7 @@
                             start_address = int(GetCTVal(subchild, 2))
                             relative_addr = absloute_address - start_address
                             # test if relative address in request specified range
-                            if relative_addr in xrange(int(GetCTVal(subchild, 1))):
+                            if relative_addr in range(int(GetCTVal(subchild, 1))):
                                 if str(iecvar["NAME"]) not in loc_vars_list:
                                     loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &server_nodes[%d].mem_area.%s[%d];" % (
                                         server_id, memarea, absloute_address))
@@ -1116,7 +1116,7 @@
                         #        two numbers are always '0.0', and the first two identify the request.
                         #        In the following if, we check for this condition by checking
                         #        if there are at least 4 or more number in the location's address.
-                        if (        relative_addr in xrange(int(GetCTVal(subchild, 2)))  # condition (a) explained above
+                        if (        relative_addr in range(int(GetCTVal(subchild, 2)))  # condition (a) explained above
                             and len(iecvar["LOC"]) < 5):                                  # condition (b) explained above
                             if str(iecvar["NAME"]) not in loc_vars_list:
                                 loc_vars.append("u16 *" + str(iecvar["NAME"]) + " = &client_requests[%d].plcv_buffer[%d];" % (client_requestid, relative_addr))
@@ -1177,7 +1177,7 @@
                         #        two numbers are always '0.0', and the first two identify the request.
                         #        In the following if, we check for this condition by checking
                         #        if there are at least 4 or more number in the location's address.
-                        if (        relative_addr in xrange(int(GetCTVal(subchild, 2)))  # condition (a) explained above
+                        if (        relative_addr in range(int(GetCTVal(subchild, 2)))  # condition (a) explained above
                             and len(iecvar["LOC"]) < 5):                                  # condition (b) explained above
                             if str(iecvar["NAME"]) not in loc_vars_list:
                                 loc_vars.append(
--- a/opc_ua/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/opc_ua/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,6 +1,6 @@
 # opcua/__init__.py
 
-from __future__ import absolute_import
+
 
 from .client import OPCUAClient
 
--- a/opc_ua/client.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/opc_ua/client.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,6 +1,6 @@
 # opcua/client.py
 
-from __future__ import absolute_import
+
 
 import os
 
@@ -158,7 +158,7 @@
         locstr = "_".join(map(str, current_location))
         name = self.BaseParams.getName()
         entries = []
-        for direction, data in self.modeldata.iteritems():
+        for direction, data in self.modeldata.items():
             iec_direction_prefix = {"input": "__I", "output": "__Q"}[direction]
             for row in data:
                 dname, ua_nsidx, ua_nodeid_type, _ua_node_id, ua_type, iec_number = row
--- a/opc_ua/opcua_client_maker.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/opc_ua/opcua_client_maker.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,5 +1,5 @@
-from __future__ import print_function
-from __future__ import absolute_import
+
+
 
 import csv
 
@@ -453,7 +453,7 @@
         self.change_callback = change_callback
 
     def append(self, value):
-        v = dict(zip(lstcolnames, value))
+        v = dict(list(zip(lstcolnames, value)))
 
         if type(v["IEC"]) != int:
             if len(self) == 0:
@@ -475,7 +475,7 @@
             self.log("Variable {} (Id={}) has invalid type\n".format(v["Name"],v["Id"]))
             return False
 
-        if len(self)>0 and v["Id"] in zip(*self)[lstcolnames.index("Id")]:
+        if len(self)>0 and v["Id"] in list(zip(*self))[lstcolnames.index("Id")]:
             self.log("Variable {} (Id={}) already in list\n".format(v["Name"],v["Id"]))
             return False
 
@@ -498,8 +498,8 @@
     def LoadCSV(self,path):
         with open(path, 'rb') as csvfile:
             reader = csv.reader(csvfile, delimiter=',', quotechar='"')
-            buf = {direction:[] for direction, _model in self.iteritems()}
-            for direction, model in self.iteritems():
+            buf = {direction:[] for direction, _model in self.items()}
+            for direction, model in self.items():
                 self[direction][:] = []
             for row in reader:
                 direction = row[0]
@@ -508,7 +508,7 @@
 
     def SaveCSV(self,path):
         with open(path, 'wb') as csvfile:
-            for direction, data in self.iteritems():
+            for direction, data in self.items():
                 writer = csv.writer(csvfile, delimiter=',',
                                 quotechar='"', quoting=csv.QUOTE_MINIMAL)
                 for row in data:
@@ -706,7 +706,7 @@
             formatdict["init"] += """
     INIT_NoAuth()"""
 
-        for direction, data in self.iteritems():
+        for direction, data in self.items():
             iec_direction_prefix = {"input": "__I", "output": "__Q"}[direction]
             for row in data:
                 name, ua_nsidx, ua_nodeid_type, _ua_node_id, ua_type, iec_number = row
@@ -751,7 +751,7 @@
     if argc > 2:
         AuthType = sys.argv[2]
         config["AuthType"] = AuthType
-        for (name, default), value in izip_longest(authParams[AuthType], sys.argv[3:]):
+        for (name, default), value in zip_longest(authParams[AuthType], sys.argv[3:]):
             if value is None:
                 if default is None:
                     raise Exception(name+" param expected")
--- a/plcopen/BlockInstanceCollector.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/BlockInstanceCollector.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # This file is part of Beremiz.
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 from collections import OrderedDict, namedtuple
 from plcopen.XSLTModelQuery import XSLTModelQuery, _StringValue, _BoolValue, _translate_args
 
--- a/plcopen/InstanceTagnameCollector.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/InstanceTagnameCollector.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # This file is part of Beremiz.
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 from plcopen.XSLTModelQuery import XSLTModelQuery
 from plcopen.types_enums import *
 
--- a/plcopen/InstancesPathCollector.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/InstancesPathCollector.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # This file is part of Beremiz.
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 from plcopen.XSLTModelQuery import XSLTModelQuery
 
 
--- a/plcopen/POUVariablesCollector.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/POUVariablesCollector.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # 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 plcopen.types_enums import CLASS_TYPES, POU_TYPES, VAR_CLASS_INFOS
 
--- a/plcopen/VariableInfoCollector.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/VariableInfoCollector.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # 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
 
 # -------------------------------------------------------------------------------
--- a/plcopen/XSLTModelQuery.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/XSLTModelQuery.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # This file is part of Beremiz.
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import os
 from lxml import etree
 import util.paths as paths
@@ -24,7 +24,7 @@
             ("GetProject", lambda *_ignored:
              [controller.GetProject(self.debug)]),
             ("GetStdLibs", lambda *_ignored:
-             [lib for lib in StdBlckLibs.values()]),
+             [lib for lib in list(StdBlckLibs.values())]),
             ("GetExtensions", lambda *_ignored:
              [ctn["types"] for ctn in controller.ConfNodeTypes])
         ]
--- a/plcopen/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -26,7 +26,7 @@
 
 # plcopen module dynamically creates its classes
 
-from __future__ import absolute_import
+
 from plcopen.plcopen import \
     PLCOpenParser, LoadProject, SaveProject, LoadPou, \
     LoadPouInstances, VarOrder, QualifierList, rect
--- a/plcopen/definitions.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/definitions.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from os.path import join
 import util.paths as paths
 from util.TranslationCatalogs import NoTranslate
--- a/plcopen/plcopen.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/plcopen.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,8 +24,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import re
 from collections import OrderedDict
 
@@ -440,7 +440,7 @@
 
     def setcontentHeader(self, contentheader):
         contentheader_obj = self.contentHeader
-        for attr, value in contentheader.iteritems():
+        for attr, value in contentheader.items():
             func = {"projectName": contentheader_obj.setname,
                     "projectVersion": contentheader_obj.setversion,
                     "authorName": contentheader_obj.setauthor,
@@ -495,7 +495,7 @@
             "ppx:types/ppx:pous/ppx:pou%s%s" %
             (("[@name!='%s']" % exclude) if exclude is not None else '',
              ("[%s]" % " or ".join(
-                 map(lambda x: "@pouType='%s'" % x, filter)))
+                 ["@pouType='%s'" % x for x in filter]))
              if len(filter) > 0 else ""),
             namespaces=PLCOpenParser.NSMAP)
     setattr(cls, "getpous", getpous)
@@ -650,7 +650,7 @@
     setattr(cls, "getpageSize", getpageSize)
 
     def setscaling(self, scaling):
-        for language, (x, y) in scaling.items():
+        for language, (x, y) in list(scaling.items()):
             self.coordinateInfo.setscaling(language, x, y)
     setattr(cls, "setscaling", setscaling)
 
@@ -749,7 +749,7 @@
 def _removeConfigurationResourceVariableByAddress(self, address):
     for varlist in self.getglobalVars():
         variables = varlist.getvariable()
-        for i in xrange(len(variables)-1, -1, -1):
+        for i in range(len(variables)-1, -1, -1):
             if variables[i].getaddress() == address:
                 variables.remove(variables[i])
 
@@ -757,7 +757,7 @@
 def _removeConfigurationResourceVariableByFilter(self, address_model):
     for varlist in self.getglobalVars():
         variables = varlist.getvariable()
-        for i in xrange(len(variables)-1, -1, -1):
+        for i in range(len(variables)-1, -1, -1):
             var_address = variables[i].getaddress()
             if var_address is not None:
                 result = address_model.match(var_address)
@@ -971,7 +971,7 @@
             # Array derived directly from an elementary type
             else:
                 basetype_name = base_type_name
-            return "ARRAY [%s] OF %s" % (",".join(map(lambda x: "%s..%s" % (x.getlower(), x.getupper()), vartype_content.getdimension())), basetype_name)
+            return "ARRAY [%s] OF %s" % (",".join(["%s..%s" % (x.getlower(), x.getupper()) for x in vartype_content.getdimension()]), basetype_name)
         # Variable type is an elementary type
         return vartype_content_name
     setattr(cls, "gettypeAsText", gettypeAsText)
@@ -1380,7 +1380,7 @@
         vars = []
         if self.interface is not None:
             reverse_types = {}
-            for name, value in VarTypes.items():
+            for name, value in list(VarTypes.items()):
                 reverse_types[value] = name
             for varlist in self.interface.getcontent():
                 vars.append((reverse_types[varlist.getLocalTag()], varlist))
--- a/plcopen/structures.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/structures.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import re
 from collections import OrderedDict
 from functools import reduce
@@ -53,7 +53,7 @@
     """
     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)]
+    return [typename for typename, _parenttype in list(TypeHierarchy.items()) if not typename.startswith("ANY") and IsOfType(typename, type)]
 
 
 DataTypeRange = dict(DataTypeRange_list)
@@ -78,7 +78,7 @@
                for libname, tc6fname in StdTC6Libs}
 StdBlckLst = [{"name": libname, "list":
                [GetBlockInfos(pous) for pous in lib.getpous()]}
-              for libname, lib in StdBlckLibs.iteritems()]
+              for libname, lib in StdBlckLibs.items()]
 
 # -------------------------------------------------------------------------------
 #                             Test identifier
@@ -148,7 +148,7 @@
     len_of_not_predifined_variable = len([True for param_type in decl if param_type not in variables])
 
     for param_type in decl:
-        if param_type in variables.keys():
+        if param_type in list(variables.keys()):
             param_name = param_type
             param_type = variables[param_type]
         elif len_of_not_predifined_variable > 1:
@@ -202,7 +202,7 @@
                 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ])
                 baseinputnumber = int(Function_decl.get("baseinputnumber", 1))
                 Function_decl["baseinputnumber"] = baseinputnumber
-                for param, value in Function_decl.iteritems():
+                for param, value in Function_decl.items():
                     if param in translate:
                         Function_decl[param] = translate[param](value)
                 Function_decl["type"] = "function"
@@ -250,13 +250,13 @@
                         store = True
                         for (InTypes, OutTypes) in ANY_TO_ANY_FILTERS.get(filter_name, []):
                             outs = reduce(lambda a, b: a or b,
-                                          map(lambda testtype: IsOfType(
+                                          [IsOfType(
                                               Function_decl["outputs"][0][1],
-                                              testtype), OutTypes))
+                                              testtype) for testtype in OutTypes])
                             inps = reduce(lambda a, b: a or b,
-                                          map(lambda testtype: IsOfType(
+                                          [IsOfType(
                                               Function_decl["inputs"][0][1],
-                                              testtype), InTypes))
+                                              testtype) for testtype in InTypes])
                             if inps and outs and Function_decl["outputs"][0][1] != Function_decl["inputs"][0][1]:
                                 store = True
                                 break
@@ -308,7 +308,7 @@
 TYPE_BLOCK_START_KEYWORDS = ["TYPE", "STRUCT"]
 TYPE_BLOCK_END_KEYWORDS = ["END_TYPE", "END_STRUCT"]
 TYPE_KEYWORDS = ["ARRAY", "OF", "T", "D", "TIME_OF_DAY", "DATE_AND_TIME"] + TYPE_BLOCK_START_KEYWORDS + TYPE_BLOCK_END_KEYWORDS
-TYPE_KEYWORDS.extend([keyword for keyword in TypeHierarchy.keys() if keyword not in TYPE_KEYWORDS])
+TYPE_KEYWORDS.extend([keyword for keyword in list(TypeHierarchy.keys()) if keyword not in TYPE_KEYWORDS])
 
 
 # Keywords for Variable Declaration
--- a/plcopen/types_enums.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/plcopen/types_enums.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,7 +3,7 @@
 # This file is part of Beremiz
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 from util.TranslationCatalogs import NoTranslate
 _ = NoTranslate
 
@@ -16,7 +16,7 @@
     ITEM_CONFIGURATION,
     ITEM_RESOURCE,
     ITEM_DATATYPE
-] = range(8)
+] = list(range(8))
 
 ITEMS_UNEDITABLE = [
     ITEM_DATATYPES,
@@ -28,7 +28,7 @@
     ITEM_CONFIGURATIONS,
     ITEM_RESOURCES,
     ITEM_PROPERTIES
-] = range(8, 17)
+] = list(range(8, 17))
 
 ITEMS_VARIABLE = [
     ITEM_VAR_LOCAL,
@@ -38,7 +38,7 @@
     ITEM_VAR_INPUT,
     ITEM_VAR_OUTPUT,
     ITEM_VAR_INOUT
-] = range(17, 24)
+] = list(range(17, 24))
 
 ITEM_CONFNODE = 25
 
@@ -70,7 +70,7 @@
                    LOCATION_GROUP,
                    LOCATION_VAR_INPUT,
                    LOCATION_VAR_OUTPUT,
-                   LOCATION_VAR_MEMORY] = range(6)
+                   LOCATION_VAR_MEMORY] = list(range(6))
 
 UNEDITABLE_NAMES = [_("User-defined POUs"), _("Functions"), _("Function Blocks"),
                     _("Programs"), _("Data Types"), _("Transitions"), _("Actions"),
--- a/py_ext/PythonEditor.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/py_ext/PythonEditor.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import keyword
 import wx.stc as stc
 
--- a/py_ext/PythonFileCTNMixin.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/py_ext/PythonFileCTNMixin.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import re
 from builtins import str as text
@@ -134,8 +134,7 @@
             return repr(content) if content else None
 
         pyextname = self.CTNName()
-        varinfos = map(
-            lambda variable: {
+        varinfos = [{
                 "name": variable.getname(),
                 "desc": repr(variable.getdesc()),
                 "onchangecode": _onchangecode(variable),
@@ -146,8 +145,7 @@
                 "IECtype": self.GetCTRoot().GetBaseType(variable.gettype()),
                 "initial": repr(variable.getinitial()),
                 "pyextname": pyextname
-            },
-            self.CodeFile.variables.variable)
+            } for variable in self.CodeFile.variables.variable]
 
         onchange_var_count = len([None for varinfo in varinfos if varinfo["onchange"]])
 
--- a/py_ext/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/py_ext/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +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.
 
-from __future__ import absolute_import
+
 from .py_ext import *
 from .PythonEditor import PythonEditor
 from .PythonFileCTNMixin import PythonFileCTNMixin
--- a/py_ext/py_ext.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/py_ext/py_ext.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 from POULibrary import POULibrary
 from py_ext.PythonFileCTNMixin import PythonFileCTNMixin
--- a/runtime/NevowServer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/NevowServer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import collections
 import shutil
@@ -78,7 +78,7 @@
 
 
 class MainPage(athena.LiveElement):
-    jsClass = u"WebInterface.PLC"
+    jsClass = "WebInterface.PLC"
     docFactory = loaders.stan(
         tags.invisible[
             tags.div(render=tags.directive('liveElement'))[
@@ -356,7 +356,7 @@
 
     def __init__(self, plcState=False, *a, **kw):
         super(WebInterface, self).__init__(*a, **kw)
-        self.jsModules.mapping[u'WebInterface'] = paths.AbsNeighbourFile(
+        self.jsModules.mapping['WebInterface'] = paths.AbsNeighbourFile(
             __file__, 'webinterface.js')
         self.plcState = plcState
         self.MainPage.setPLCState(plcState)
@@ -365,7 +365,7 @@
         return self.MainPage.getHMI()
 
     def LoadHMI(self, hmi, jsmodules):
-        for name, path in jsmodules.iteritems():
+        for name, path in jsmodules.items():
             self.jsModules.mapping[name] = os.path.join(WorkingDir, path)
         self.MainPage.setPLCStartedHMI(hmi)
 
--- a/runtime/PLCObject.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/PLCObject.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,7 +22,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 
-from __future__ import absolute_import
+
 from threading import Thread, Lock, Event, Condition
 import ctypes
 import os
@@ -393,7 +393,7 @@
             for filename in filenames:
                 name, ext = os.path.splitext(filename)
                 if name.upper().startswith("RUNTIME") and ext.upper() == ".PY":
-                    execfile(os.path.join(self.workingdir, filename), self.python_runtime_vars)
+                    exec(compile(open(os.path.join(self.workingdir, filename), "rb").read(), os.path.join(self.workingdir, filename), 'exec'), self.python_runtime_vars)
                     for methodname in MethodNames:
                         method = self.python_runtime_vars.get("_%s_%s" % (name, methodname), None)
                         if method is not None:
@@ -561,7 +561,7 @@
 
     @RunInMain
     def _GetPLCstatus(self):
-        return self.PLCStatus, map(self.GetLogCount, xrange(LogLevelsCount))
+        return self.PLCStatus, list(map(self.GetLogCount, range(LogLevelsCount)))
 
     @RunInMain
     def GetPLCID(self):
@@ -598,7 +598,7 @@
 
     @RunInMain
     def PurgeBlobs(self):
-        for fd, _path, _md5sum in self.blobs.values():
+        for fd, _path, _md5sum in list(self.blobs.values()):
             os.close(fd)
         self._init_blobs()
 
--- a/runtime/PyroServer.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/PyroServer.py	Fri Oct 28 12:39:15 2022 +0800
@@ -9,8 +9,8 @@
 
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import sys
 import os
 
--- a/runtime/ServicePublisher.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/ServicePublisher.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,8 +22,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import socket
 import threading
 import zeroconf
--- a/runtime/Stunnel.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/Stunnel.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,5 +1,5 @@
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 from binascii import b2a_hqx
 try:
--- a/runtime/WampClient.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/WampClient.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,8 +22,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import time
 import json
 import os
@@ -110,12 +110,12 @@
     def onConnect(self):
         if "secret" in self.config.extra:
             user = self.config.extra["ID"]
-            self.join(u"Automation", [u"wampcra"], user)
+            self.join("Automation", ["wampcra"], user)
         else:
-            self.join(u"Automation")
+            self.join("Automation")
 
     def onChallenge(self, challenge):
-        if challenge.method == u"wampcra":
+        if challenge.method == "wampcra":
             if "secret" in self.config.extra:
                 secret = self.config.extra["secret"].encode('utf8')
                 signature = auth.compute_wcs(
@@ -139,7 +139,7 @@
                 registerOptions = None
                 print(_("TypeError register option: {}".format(e)))
 
-            self.register(GetCallee(name), u'.'.join((ID, name)), registerOptions)
+            self.register(GetCallee(name), '.'.join((ID, name)), registerOptions)
 
         for name in SubscribedEvents:
             self.subscribe(GetCallee(name), text(name))
@@ -185,7 +185,7 @@
             _transportFactory = None
 
     def setClientFactoryOptions(self, options):
-        for key, value in options.items():
+        for key, value in list(options.items()):
             if key in ["maxDelay", "initialDelay", "maxRetries", "factor", "jitter"]:
                 setattr(self, key, value)
 
@@ -214,7 +214,7 @@
             _("WAMP configuration error:"))
 
 def UpdateWithDefault(d1, d2):
-    for k, v in d2.items():
+    for k, v in list(d2.items()):
         d1.setdefault(k, v)
 
 def GetConfiguration():
--- a/runtime/Worker.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/Worker.py	Fri Oct 28 12:39:15 2022 +0800
@@ -7,7 +7,7 @@
 #
 # See COPYING.Runtime file for copyrights details.
 
-from __future__ import absolute_import
+
 import sys
 from threading import Lock, Condition, Thread
 
--- a/runtime/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import traceback
 import sys
 
--- a/runtime/monotonic_time.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/monotonic_time.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 SOFTWARE.
 '''
 
-from __future__ import print_function
-from __future__ import unicode_literals
+
+
 
 __author__ = 'Gavin Beatty <gavinbeatty@gmail.com>'
 __version__ = '2.1.0.dev0'
--- a/runtime/spawn_subprocess.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/spawn_subprocess.py	Fri Oct 28 12:39:15 2022 +0800
@@ -3,8 +3,8 @@
 
 # subset of subprocess built-in module using posix_spawn rather than fork.
 
-from __future__ import print_function
-from __future__ import absolute_import
+
+
 import os
 import signal
 import shlex
--- a/runtime/typemapping.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/typemapping.py	Fri Oct 28 12:39:15 2022 +0800
@@ -4,7 +4,7 @@
 # See COPYING.Runtime file for copyrights details.
 #
 
-from __future__ import absolute_import
+
 import ctypes
 from ctypes import *
 from datetime import timedelta as td
@@ -74,7 +74,7 @@
 TypeTranslator = SameEndianessTypeTranslator
 
 # Construct debugger natively supported types
-DebugTypesSize = dict([(key, sizeof(t)) for key, (t, p, u) in SameEndianessTypeTranslator.iteritems() if t is not None])
+DebugTypesSize = dict([(key, sizeof(t)) for key, (t, p, u) in SameEndianessTypeTranslator.items() if t is not None])
 
 
 def UnpackDebugBuffer(buff, indexes):
--- a/runtime/xenomai.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/runtime/xenomai.py	Fri Oct 28 12:39:15 2022 +0800
@@ -4,7 +4,7 @@
 # See COPYING.Runtime file for copyrights details.
 #
 
-from __future__ import absolute_import
+
 from ctypes import CDLL, RTLD_GLOBAL, pointer, c_int, POINTER, c_char, create_string_buffer
 
 
--- a/svghmi/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/svghmi/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -6,5 +6,5 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 from svghmi.svghmi import *
--- a/svghmi/hmi_tree.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/svghmi/hmi_tree.py	Fri Oct 28 12:39:15 2022 +0800
@@ -6,8 +6,8 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
-from itertools import izip, imap
+
+
 from pprint import pformat
 import weakref
 import hashlib
@@ -22,7 +22,7 @@
     "HMI_REAL":{}
 }
 
-HMI_TYPES = HMI_TYPES_DESC.keys()
+HMI_TYPES = list(HMI_TYPES_DESC.keys())
 
 class HMITreeNode(object):
     def __init__(self, path, name, nodetype, iectype = None, vartype = None, cpath = None, hmiclass = None):
@@ -56,7 +56,7 @@
         for child in self.children:
             if child.path is not None:
                 in_common = 0
-                for child_path_item, node_path_item in izip(child.path, node.path):
+                for child_path_item, node_path_item in zip(child.path, node.path):
                     if child_path_item == node_path_item:
                         in_common +=1
                     else:
@@ -105,7 +105,7 @@
         res = etree.Element(self.nodetype, **attribs)
 
         if hasattr(self, "children"):
-            for child_etree in imap(lambda c:c.etree(), self.children):
+            for child_etree in map(lambda c:c.etree(), self.children):
                 res.append(child_etree)
 
         return res
@@ -150,7 +150,7 @@
         s = hashlib.new('md5')
         self._hash(s)
         # limit size to HMI_HASH_SIZE as in svghmi.c
-        return map(ord,s.digest())[:8]
+        return list(map(ord,s.digest()))[:8]
 
     def _hash(self, s):
         s.update(str((self.name,self.nodetype)))
--- a/svghmi/i18n.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/svghmi/i18n.py	Fri Oct 28 12:39:15 2022 +0800
@@ -6,7 +6,7 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 from lxml import etree
 import os
 import sys
@@ -40,7 +40,7 @@
             poedit_path = None
 
     else:
-        if os.environ.has_key("SNAP"):
+        if "SNAP" in os.environ:
             MessageBoxOnce("Launching POEdit with xdg-open",
                     "Confined app can't launch POEdit directly.\n"+
                         "Instead, PO/POT file is passed to xdg-open.\n"+
@@ -131,7 +131,7 @@
         langs.append((langname,langcode))
 
         broken = False
-        for msgid, msg in translation.iteritems():
+        for msgid, msg in translation.items():
             broken = True
             errcallback(_('{}: Unused translation "{}":"{}"\n').format(langcode,msgid,msg))
         if broken or langcode in broken_lang:
@@ -246,13 +246,13 @@
 
     def write(self, fp):
         timestamp = time.strftime('%Y-%m-%d %H:%M+%Z')
-        print >> fp, pot_header % {'time': timestamp}
+        print(pot_header % {'time': timestamp}, file=fp)
         reverse = {}
-        for k, v in self.__messages.items():
+        for k, v in list(self.__messages.items()):
             keys = list(v)
             keys.sort()
             reverse.setdefault(tuple(keys), []).append((k, v))
-        rkeys = reverse.keys()
+        rkeys = list(reverse.keys())
         rkeys.sort()
         for rkey in rkeys:
             rentries = reverse[rkey]
@@ -267,12 +267,12 @@
                     if len(locline) + len(s) <= 78:
                         locline = locline + s
                     else:
-                        print >> fp, locline
+                        print(locline, file=fp)
                         locline = locpfx + s
                 if len(locline) > len(locpfx):
-                    print >> fp, locline
-                print >> fp, 'msgid', normalize(k)
-                print >> fp, 'msgstr ""\n'
+                    print(locline, file=fp)
+                print('msgid', normalize(k), file=fp)
+                print('msgstr ""\n', file=fp)
 
 
 class POReader:
@@ -321,8 +321,8 @@
             # This is a message with plural forms
             elif l.startswith('msgid_plural'):
                 if section != ID:
-                    print >> sys.stderr, 'msgid_plural not preceded by msgid on %s:%d' %\
-                        (infile, lno)
+                    print('msgid_plural not preceded by msgid on %s:%d' %\
+                        (infile, lno), file=sys.stderr)
                     sys.exit(1)
                 l = l[12:]
                 msgid += '\0' # separator of singular and plural
@@ -332,16 +332,16 @@
                 section = STR
                 if l.startswith('msgstr['):
                     if not is_plural:
-                        print >> sys.stderr, 'plural without msgid_plural on %s:%d' %\
-                            (infile, lno)
+                        print('plural without msgid_plural on %s:%d' %\
+                            (infile, lno), file=sys.stderr)
                         sys.exit(1)
                     l = l.split(']', 1)[1]
                     if msgstr:
                         msgstr += '\0' # Separator of the various plural forms
                 else:
                     if is_plural:
-                        print >> sys.stderr, 'indexed msgstr required for plural on  %s:%d' %\
-                            (infile, lno)
+                        print('indexed msgstr required for plural on  %s:%d' %\
+                            (infile, lno), file=sys.stderr)
                         sys.exit(1)
                     l = l[6:]
             # Skip empty lines
@@ -354,9 +354,9 @@
             elif section == STR:
                 msgstr += l
             else:
-                print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
-                      'before:'
-                print >> sys.stderr, l
+                print('Syntax error on %s:%d' % (infile, lno), \
+                      'before:', file=sys.stderr)
+                print(l, file=sys.stderr)
                 sys.exit(1)
         # Add last entry
         if section == STR:
--- a/svghmi/svghmi.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/svghmi/svghmi.py	Fri Oct 28 12:39:15 2022 +0800
@@ -6,7 +6,7 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import os
 import sys
 import shutil
@@ -307,7 +307,7 @@
     default_cmds={
         "launch":"cmd.exe /c 'start msedge {url}'",
         "watchdog":"cmd.exe /k 'echo watchdog for {url} !'"}
-elif os.environ.has_key("SNAP"):
+elif "SNAP" in os.environ:
     default_cmds={
         "launch":"xdg-open {url}",
         "watchdog":"echo Watchdog for {name} !"}
@@ -443,7 +443,7 @@
         for line in result.split():
             strippedline = line.strip()
             attrs = dict(
-                zip(InkscapeGeomColumns, line.strip().split(',')))
+                list(zip(InkscapeGeomColumns, line.strip().split(','))))
 
             res.append(etree.Element("bbox", **attrs))
 
--- a/svghmi/svghmi_server.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/svghmi/svghmi_server.py	Fri Oct 28 12:39:15 2022 +0800
@@ -5,7 +5,7 @@
 # Copyright (C) 2019: Edouard TISSERANT
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import errno
 from threading import RLock, Timer
 import os, time
@@ -273,7 +273,7 @@
                 break
 
 def AddPathToSVGHMIServers(path, factory, *args, **kwargs):
-    for k,v in svghmi_servers.iteritems():
+    for k,v in svghmi_servers.items():
         svghmi_root, svghmi_listener, path_list = v
         svghmi_root.putChild(path, factory(*args, **kwargs))
 
--- a/svghmi/ui.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/svghmi/ui.py	Fri Oct 28 12:39:15 2022 +0800
@@ -6,7 +6,7 @@
 #
 # See COPYING file for copyrights details.
 
-from __future__ import absolute_import
+
 import os
 import hashlib
 import weakref
@@ -14,7 +14,7 @@
 import tempfile
 from threading import Thread, Lock
 from functools import reduce
-from itertools import izip
+
 from operator import or_
 from tempfile import NamedTemporaryFile
 
@@ -34,7 +34,7 @@
 # When running as a confined Snap, /tmp isn't accessible from the outside
 # and Widget DnD to Inkscape can't work, since it can't find generated svg 
 # This forces tmp directory in $SNAP_USER_DATA, accessible from other apps
-if os.environ.has_key("SNAP"):
+if "SNAP" in os.environ:
      NamedTemporaryFile_orig = NamedTemporaryFile
      tmpdir = os.path.join(os.environ["SNAP_USER_DATA"], ".tmp")
      if not os.path.exists(tmpdir):
@@ -249,9 +249,7 @@
         accepts = self.argdesc.get("accepts").split(',')
         self.setValidity(
             reduce(or_,
-                   map(lambda typename: 
-                           models[typename].match(txt) is not None,
-                       accepts), 
+                   [models[typename].match(txt) is not None for typename in accepts], 
                    False)
             if accepts and txt else None)
         self.ParentObj.RegenSVGLater()
@@ -283,9 +281,7 @@
         event.Skip()
     
 def KeepDoubleNewLines(txt):
-    return "\n\n".join(map(
-        lambda s:re.sub(r'\s+',' ',s),
-        txt.split("\n\n")))
+    return "\n\n".join([re.sub(r'\s+',' ',s) for s in txt.split("\n\n")])
 
 _conf_key = "SVGHMIWidgetLib"
 _preview_height = 200
@@ -653,7 +649,7 @@
             # TODO: check that only last arg has multiple ordinality
             args += [args[-1]]*(len(prefillargs)-len(args))
         self.args_box.Show(len(args)!=0)
-        for arg, prefillarg in izip(args,prefillargs):
+        for arg, prefillarg in zip(args,prefillargs):
             self.AddArgToSignature(arg, prefillarg)
 
         # TODO support predefined path count (as for XYGraph)
--- a/targets/Generic/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/targets/Generic/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from ..toolchain_makefile import toolchain_makefile
 
 
--- a/targets/Linux/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/targets/Linux/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from ..toolchain_gcc import toolchain_gcc
 
 
--- a/targets/Win32/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/targets/Win32/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from ..toolchain_gcc import toolchain_gcc
 
 
--- a/targets/Xenomai/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/targets/Xenomai/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 from ..toolchain_gcc import toolchain_gcc
 
 
--- a/targets/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/targets/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -35,7 +35,7 @@
 """
 
 
-from __future__ import absolute_import
+
 from os import listdir, path
 import util.paths as paths
 
@@ -69,12 +69,12 @@
     targetchoices = ""
 
     # Get all xsd toolchains
-    for toolchainname, xsdfilename in toolchains.iteritems():
+    for toolchainname, xsdfilename in toolchains.items():
         if path.isfile(xsdfilename):
             DictXSD_toolchain["toolchain_"+toolchainname] = open(xsdfilename).read()
 
     # Get all xsd targets
-    for target_name, nfo in targets.iteritems():
+    for target_name, nfo in targets.items():
         xsd_string = open(nfo["xsd"]).read()
         targetchoices += xsd_string % dict(DictXSD_toolchain,
                                            target_name=target_name)
--- a/targets/toolchain_gcc.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/targets/toolchain_gcc.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import re
 import operator
@@ -52,9 +52,9 @@
         Returns list of builder specific CFLAGS
         """
         cflags = [self.CTRInstance.GetTarget().getcontent().getCFLAGS()]
-        if os.environ.has_key("CFLAGS"):
+        if "CFLAGS" in os.environ:
             cflags.append(os.environ["CFLAGS"])
-        if os.environ.has_key("SYSROOT"):
+        if "SYSROOT" in os.environ:
             cflags.append("--sysroot="+os.environ["SYSROOT"])
         return cflags
 
@@ -64,9 +64,9 @@
         """
         ldflags = self.CTRInstance.LDFLAGS + \
             [self.CTRInstance.GetTarget().getcontent().getLDFLAGS()]
-        if os.environ.has_key("LDFLAGS"):
-            ldflags.append(os.environ["LDFLAGS"])
-        if os.environ.has_key("SYSROOT"):
+        if "LDLAGS" in os.environ:
+            ldflags.append(os.environ["LDLAGS"])
+        if "SYSROOT" in os.environ:
             ldflags.append("--sysroot="+os.environ["SYSROOT"])
         return ldflags
 
@@ -128,7 +128,7 @@
         self.append_cfile_deps(src, deps)
         # recurse through deps
         # TODO detect cicular deps.
-        return reduce(operator.concat, map(self.concat_deps, deps), src)
+        return reduce(operator.concat, list(map(self.concat_deps, deps)), src)
 
     def check_and_update_hash_and_deps(self, bn):
         # Get latest computed hash and deps
@@ -148,7 +148,7 @@
             self.srcmd5[bn] = (newhash, deps)
         # recurse through deps
         # TODO detect cicular deps.
-        return reduce(operator.and_, map(self.check_and_update_hash_and_deps, deps), match)
+        return reduce(operator.and_, list(map(self.check_and_update_hash_and_deps, deps)), match)
 
     def calc_source_md5(self):
         wholesrcdata = ""
--- a/targets/toolchain_makefile.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/targets/toolchain_makefile.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import re
 import operator
@@ -83,7 +83,7 @@
                     deps.append(depfn)
         # recurse through deps
         # TODO detect cicular deps.
-        return reduce(operator.concat, map(self.concat_deps, deps), src)
+        return reduce(operator.concat, list(map(self.concat_deps, deps)), src)
 
     def build(self):
         srcfiles = []
--- a/tests/ide_tests/conftest.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/tests/ide_tests/conftest.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import sys
 
--- a/tests/ide_tests/load_and_build_tests.pytest/test_application.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/tests/ide_tests/load_and_build_tests.pytest/test_application.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import sys
 import unittest
--- a/tests/ide_tests/wx_widgets.pytest/test_CustomIntCtrl.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/tests/ide_tests/wx_widgets.pytest/test_CustomIntCtrl.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import division
+
+
 import unittest
 import time
 
--- a/util/BitmapLibrary.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/util/BitmapLibrary.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 
 import wx
--- a/util/ExceptionHandler.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/util/ExceptionHandler.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import sys
 import time
@@ -93,7 +93,7 @@
 
 
 def format_namespace(d, indent='    '):
-    return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()])
+    return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.items()])
 
 
 ignored_exceptions = []  # a problem with a line in a module is only reported once per session
@@ -129,7 +129,7 @@
         if not os.path.exists(path):
             os.mkdir(path)
         output = open(bug_report_path, 'w')
-        lst = info.keys()
+        lst = list(info.keys())
         lst.sort()
         for a in lst:
             line = a + ":\n" + str(info[a]) + "\n\n"
--- a/util/MiniTextControler.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/util/MiniTextControler.py	Fri Oct 28 12:39:15 2022 +0800
@@ -27,7 +27,7 @@
 """
 
 
-from __future__ import absolute_import
+
 import os
 
 
--- a/util/ProcessLogger.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/util/ProcessLogger.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import sys
 import subprocess
@@ -100,8 +100,7 @@
 
         if encoding is None:
             encoding = fsencoding
-        self.Command = [self.Command[0].encode(fsencoding)]+map(
-            lambda x: x.encode(encoding), self.Command[1:])
+        self.Command = [self.Command[0].encode(fsencoding)]+[x.encode(encoding) for x in self.Command[1:]]
 
         self.finish_callback = finish_callback
         self.no_stdout = no_stdout
--- a/util/TranslationCatalogs.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/util/TranslationCatalogs.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 from six.moves import builtins
 import wx
--- a/util/misc.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/util/misc.py	Fri Oct 28 12:39:15 2022 +0800
@@ -27,7 +27,7 @@
 """
 
 
-from __future__ import absolute_import
+
 import os,sys
 import random
 from functools import reduce
--- a/util/paths.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/util/paths.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import sys
 from builtins import str as text
--- a/version.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/version.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,9 +23,9 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import unicode_literals
-from __future__ import print_function
+
+
+
 
 import os
 
--- a/wxglade_hmi/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/wxglade_hmi/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -22,5 +22,5 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from __future__ import absolute_import
+
 from wxglade_hmi.wxglade_hmi import *
--- a/wxglade_hmi/wxglade_hmi.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/wxglade_hmi/wxglade_hmi.py	Fri Oct 28 12:39:15 2022 +0800
@@ -24,7 +24,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
+
 import os
 import sys
 import shutil
--- a/xmlclass/__init__.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/xmlclass/__init__.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,7 +23,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 # Package initialisation
-from __future__ import absolute_import
+
 from .xmlclass import (ClassFactory,
                        GenerateParser,
                        DefaultElementClass,
--- a/xmlclass/xmlclass.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/xmlclass/xmlclass.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import re
 import datetime
@@ -107,7 +107,7 @@
 [
     SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE,
     ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT,
-] = range(13)
+] = list(range(13))
 
 
 def NotSupportedYet(type):
@@ -128,7 +128,7 @@
     """
     first = indent * 2
     second = first + len(balise) + 1
-    return u'\t'.expandtabs(first), u'\t'.expandtabs(second)
+    return '\t'.expandtabs(first), '\t'.expandtabs(second)
 
 
 def GetAttributeValue(attr, extract=True):
@@ -144,9 +144,9 @@
         return text(unescape(attr.childNodes[0].data))
     else:
         # content is a CDATA
-        txt = u''
+        txt = ''
         for node in attr.childNodes:
-            if not (node.nodeName == "#text" and node.data.strip() == u''):
+            if not (node.nodeName == "#text" and node.data.strip() == ''):
                 txt += text(unescape(node.data))
         return text
 
@@ -634,7 +634,7 @@
                 if infos["type"] != ANY:
                     DefaultElementClass.__setattr__(value, "tag", element_name)
                 return value
-        return [initial_value() for dummy in xrange(infos["minOccurs"])]
+        return [initial_value() for dummy in range(infos["minOccurs"])]
     else:
         return []
 
@@ -691,13 +691,13 @@
             choices_dict[choice_name] = infos
     prefix = ("%s:" % factory.TargetNamespace
               if factory.TargetNamespace is not None else "")
-    choices_xpath = "|".join(map(lambda x: prefix + x, choices_dict.keys()))
+    choices_xpath = "|".join([prefix + x for x in list(choices_dict.keys())])
 
     def GetContentInitial():
         content_name, infos = choices[0]
         if content_name == "sequence":
             content_value = []
-            for dummy in xrange(infos["minOccurs"]):
+            for dummy in range(infos["minOccurs"]):
                 for element_infos in infos["elements"]:
                     content_value.extend(GetElementInitialValue(factory, element_infos))
         else:
@@ -801,7 +801,7 @@
         if namespace is None:
             if name in self.Namespaces[self.SchemaNamespace]:
                 return self.Namespaces[self.SchemaNamespace][name]
-            for space, elements in self.Namespaces.iteritems():
+            for space, elements in self.Namespaces.items():
                 if space != self.SchemaNamespace and name in elements:
                     return elements[name]
             parts = name.split("_", 1)
@@ -843,7 +843,7 @@
         if namespace is None:
             if name in self.Namespaces[self.SchemaNamespace]:
                 return name, None
-            for space, elements in self.Namespaces.items():
+            for space, elements in list(self.Namespaces.items()):
                 if space != self.SchemaNamespace and name in elements:
                     return name, None
             parts = name.split("_", 1)
@@ -883,7 +883,7 @@
 
     def ExtractNodeAttrs(self, element_name, node, valid_attrs):
         attrs = {}
-        for qualified_name, attr in node._attrs.items():
+        for qualified_name, attr in list(node._attrs.items()):
             namespace, name = DecomposeQualifiedName(qualified_name)
             if name in valid_attrs:
                 infos = self.GetQualifiedNameInfos(name, namespace)
@@ -1016,14 +1016,14 @@
     def GetEquivalentParents(self, parent):
         return reduce(lambda x, y: x + y,
                       [[p] + self.GetEquivalentParents(p)
-                       for p in self.EquivalentClassesParent.get(parent, {}).keys()], [])
+                       for p in list(self.EquivalentClassesParent.get(parent, {}).keys())], [])
 
     def CreateClasses(self):
         """
         Method that generates the classes
         """
         self.ParseSchema()
-        for name, infos in self.Namespaces[self.TargetNamespace].items():
+        for name, infos in list(self.Namespaces[self.TargetNamespace].items()):
             if infos["type"] == ELEMENT:
                 if not isinstance(infos["elmt_type"], string_types) and \
                    infos["elmt_type"]["type"] == COMPLEXTYPE:
@@ -1055,9 +1055,9 @@
                                not isinstance(result, string_types):
                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
 
-        for name, parents in self.ComputedClassesLookUp.iteritems():
+        for name, parents in self.ComputedClassesLookUp.items():
             if isinstance(parents, dict):
-                computed_classes = parents.items()
+                computed_classes = list(parents.items())
             elif parents[1] is not None:
                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
             else:
@@ -1101,7 +1101,7 @@
                 if self.FileName is not None:
                     classinfos["base"] = self.ComputedClasses[self.FileName].get(result["name"], None)
                     if classinfos["base"] is None:
-                        for filename, classes in self.ComputedClasses.iteritems():
+                        for filename, classes in self.ComputedClasses.items():
                             if filename != self.FileName:
                                 classinfos["base"] = classes.get(result["name"], None)
                                 if classinfos["base"] is not None:
@@ -1197,12 +1197,12 @@
         """
         Method that print the classes generated
         """
-        items = self.ComputedClasses.items()
+        items = list(self.ComputedClasses.items())
         items.sort()
         if self.FileName is not None:
             for filename, classes in items:
                 print("File '%s':" % filename)
-                class_items = classes.items()
+                class_items = list(classes.items())
                 class_items.sort()
                 for classname, xmlclass in class_items:
                     print("%s: %s" % (classname, str(xmlclass)))
@@ -1211,7 +1211,7 @@
                 print("%s: %s" % (classname, str(xmlclass)))
 
     def PrintClassNames(self):
-        classnames = self.XMLClassDefinitions.keys()
+        classnames = list(self.XMLClassDefinitions.keys())
         classnames.sort()
         for classname in classnames:
             print(classname)
@@ -1319,9 +1319,7 @@
                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
                     values = self.findall(element_name)
                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
-                        return map(lambda value:
-                                   element_infos["elmt_type"]["extract"](value.text, extract=False),
-                                   values)
+                        return [element_infos["elmt_type"]["extract"](value.text, extract=False) for value in values]
                     return values
                 else:
                     value = self.find(element_name)
@@ -1375,13 +1373,11 @@
                     self.remove(element)
 
                 if value is not None:
-                    element_idx = elements.keys().index(name)
+                    element_idx = list(elements.keys()).index(name)
                     if element_idx > 0:
-                        previous_elements_xpath = "|".join(map(
-                            lambda x: prefix + x
+                        previous_elements_xpath = "|".join([prefix + x
                             if x != "content"
-                            else elements["content"]["elmt_type"]["choices_xpath"].path,
-                            elements.keys()[:element_idx]))
+                            else elements["content"]["elmt_type"]["choices_xpath"].path for x in list(elements.keys())[:element_idx]])
 
                         insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
                     else:
@@ -1487,7 +1483,7 @@
                 children.extend(self.getElementAttributes())
             if "base" in classinfos:
                 children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"])
-            for element_name, element in elements.items():
+            for element_name, element in list(elements.items()):
                 if element["minOccurs"] == 0:
                     use = "optional"
                 if element_name == "content" and element["type"] == CHOICE:
@@ -1587,7 +1583,7 @@
             if element["type"] != CHOICE:
                 initial = GetElementInitialValue(factory, element)
                 if initial is not None:
-                    map(self.append, initial)
+                    list(map(self.append, initial))
     return initMethod
 
 
@@ -1842,7 +1838,7 @@
         if targetNamespace is not None:
             self.RootNSMAP = {
                 name if targetNamespace != uri else None: uri
-                for name, uri in namespaces.iteritems()}
+                for name, uri in namespaces.items()}
         else:
             self.RootNSMAP = namespaces
         self.BaseClass = base_class
@@ -1945,7 +1941,7 @@
     ComputedClasses = factory.CreateClasses()
     if factory.FileName is not None:
         ComputedClasses = ComputedClasses[factory.FileName]
-    BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
+    BaseClass = [(name, XSDclass) for name, XSDclass in list(ComputedClasses.items()) if XSDclass.IsBaseClass]
 
     parser.initMembers(
         factory.NSMAP,
--- a/xmlclass/xsdschema.py	Mon Mar 27 10:19:14 2023 +0200
+++ b/xmlclass/xsdschema.py	Fri Oct 28 12:39:15 2022 +0800
@@ -23,8 +23,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 
-from __future__ import absolute_import
-from __future__ import print_function
+
+
 import os
 import re
 import datetime
@@ -32,7 +32,7 @@
 from xml.dom import minidom
 from future.builtins import round
 from six import string_types
-from past.builtins import long
+from past.builtins import int
 
 from xmlclass.xmlclass import *
 
@@ -77,9 +77,9 @@
 
 
 DEFAULT_FACETS = GenerateDictFacets(["pattern", "whiteSpace", "enumeration"])
-NUMBER_FACETS = GenerateDictFacets(DEFAULT_FACETS.keys() + ["maxInclusive", "maxExclusive", "minInclusive", "minExclusive"])
-DECIMAL_FACETS = GenerateDictFacets(NUMBER_FACETS.keys() + ["totalDigits", "fractionDigits"])
-STRING_FACETS = GenerateDictFacets(DEFAULT_FACETS.keys() + ["length", "minLength", "maxLength"])
+NUMBER_FACETS = GenerateDictFacets(list(DEFAULT_FACETS.keys()) + ["maxInclusive", "maxExclusive", "minInclusive", "minExclusive"])
+DECIMAL_FACETS = GenerateDictFacets(list(NUMBER_FACETS.keys()) + ["totalDigits", "fractionDigits"])
+STRING_FACETS = GenerateDictFacets(list(DEFAULT_FACETS.keys()) + ["length", "minLength", "maxLength"])
 
 ALL_FACETS = ["pattern", "whiteSpace", "enumeration", "maxInclusive",
               "maxExclusive", "minInclusive", "minExclusive", "totalDigits",
@@ -204,7 +204,7 @@
                 if len(facets) == 0:
                     facets[facettype] = ([value], False)
                     continue
-                elif facets.keys() == [facettype]:
+                elif list(facets.keys()) == [facettype]:
                     facets[facettype][0].append(value)
                     continue
                 else:
@@ -302,14 +302,14 @@
             facets[facettype] = (value, facet.get("fixed", False))
 
         # Report not redefined facet from base type to new created type
-        for facettype, facetvalue in basetypeinfos["facets"].items():
+        for facettype, facetvalue in list(basetypeinfos["facets"].items()):
             if facettype not in facets:
                 facets[facettype] = facetvalue
 
         # Generate extract value for new created type
         def ExtractSimpleTypeValue(attr, extract=True):
             value = basetypeinfos["extract"](attr, extract)
-            for facetname, (facetvalue, _facetfixed) in facets.items():
+            for facetname, (facetvalue, _facetfixed) in list(facets.items()):
                 if facetvalue is not None:
                     if facetname == "enumeration" and value not in facetvalue:
                         raise ValueError("\"%s\" not in enumerated values" % value)
@@ -328,7 +328,7 @@
                     elif facetname == "maxExclusive" and value >= facetvalue:
                         raise ValueError("value must be lesser than %s" % str(facetvalue))
                     elif facetname == "pattern":
-                        model = re.compile("(?:%s)?$" % "|".join(map(lambda x: "(?:%s)" % x, facetvalue)))
+                        model = re.compile("(?:%s)?$" % "|".join(["(?:%s)" % x for x in facetvalue]))
                         result = model.match(value)
                         if result is None:
                             if len(facetvalue) > 1:
@@ -343,7 +343,7 @@
             return value
 
         def CheckSimpleTypeValue(value):
-            for facetname, (facetvalue, _facetfixed) in facets.items():
+            for facetname, (facetvalue, _facetfixed) in list(facets.items()):
                 if facetvalue is not None:
                     if facetname == "enumeration" and value not in facetvalue:
                         return False
@@ -362,7 +362,7 @@
                     elif facetname == "maxExclusive" and value >= facetvalue:
                         return False
                     elif facetname == "pattern":
-                        model = re.compile("(?:%s)?$" % "|".join(map(lambda x: "(?:%s)" % x, facetvalue)))
+                        model = re.compile("(?:%s)?$" % "|".join(["(?:%s)" % x for x in facetvalue]))
                         result = model.match(value)
                         if result is None:
                             if len(facetvalue) > 1:
@@ -372,7 +372,7 @@
             return True
 
         def SimpleTypeInitialValue():
-            for facetname, (facetvalue, _facetfixed) in facets.items():
+            for facetname, (facetvalue, _facetfixed) in list(facets.items()):
                 if facetvalue is not None:
                     if facetname == "enumeration":
                         return facetvalue[0]
@@ -515,7 +515,7 @@
     if base is not None:
         basetypeinfos = factory.FindSchemaElement(base)
         if not isinstance(basetypeinfos, string_types) and basetypeinfos["type"] == COMPLEXTYPE:
-            attrnames = dict(map(lambda x: (x["name"], True), basetypeinfos["attributes"]))
+            attrnames = dict([(x["name"], True) for x in basetypeinfos["attributes"]])
 
     for element in elements:
         if element["type"] == ATTRIBUTE:
@@ -996,7 +996,7 @@
     elif isinstance(schema, dict):
         if not isinstance(reference, dict) or len(schema) != len(reference):
             return False
-        for name, value in schema.items():
+        for name, value in list(schema.items()):
             ref_value = reference.get(name, None)
             if ref_value is None and value is not None:
                 return False
@@ -1061,7 +1061,7 @@
             if child.nodeType == self.Document.ELEMENT_NODE:
                 schema = child
                 break
-        for qualified_name, attr in schema._attrs.items():
+        for qualified_name, attr in list(schema._attrs.items()):
             namespace, name = DecomposeQualifiedName(qualified_name)
             if namespace == "xmlns":
                 value = GetAttributeValue(attr)
@@ -2244,7 +2244,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, (int, long))
+        "check": lambda x: isinstance(x, int)
     },
 
     "hexBinary": {
@@ -2254,7 +2254,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: ("%."+str(int(round(len("%X" % x)/2.)*2))+"X") % x),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, (int, long))
+        "check": lambda x: isinstance(x, int)
     },
 
     "integer": {