beremiz

automated conversion using 2to3-3.9 tool
python3
2022-10-28, GP Orcullo
f62625418bff
Parents fda6c1a37662
Children a80a66ba52d6
automated conversion using 2to3-3.9 tool

cmd used: 2to3-3.9 -w
  • +5 -5
    Beremiz.py
  • +31 -31
    BeremizIDE.py
  • +3 -3
    Beremiz_service.py
  • +1 -1
    CLIController.py
  • +1 -1
    CodeFileTreeNode.py
  • +6 -6
    ConfigTreeNode.py
  • +55 -55
    IDEFrame.py
  • +1 -1
    NativeLib.py
  • +21 -21
    PLCControler.py
  • +18 -18
    PLCGenerator.py
  • +25 -25
    PLCOpenEditor.py
  • +1 -1
    POULibrary.py
  • +3 -3
    PSKManagement.py
  • +22 -25
    ProjectController.py
  • +2 -2
    XSLTransform.py
  • +1 -1
    bacnet/__init__.py
  • +1 -1
    bacnet/bacnet.py
  • +1 -1
    c_ext/CFileEditor.py
  • +1 -1
    c_ext/__init__.py
  • +1 -1
    c_ext/c_ext.py
  • +1 -1
    canfestival/NetworkEditor.py
  • +1 -1
    canfestival/SlaveEditor.py
  • +1 -1
    canfestival/__init__.py
  • +3 -3
    canfestival/canfestival.py
  • +16 -15
    canfestival/config_utils.py
  • +1 -1
    connectors/ConnectorBase.py
  • +2 -2
    connectors/PYRO/PSK_Adapter.py
  • +4 -3
    connectors/PYRO/__init__.py
  • +1 -1
    connectors/PYRO_dialog.py
  • +1 -1
    connectors/SchemeEditor.py
  • +2 -2
    connectors/WAMP/__init__.py
  • +1 -1
    connectors/WAMP_dialog.py
  • +0 -1
    connectors/__init__.py
  • +1 -1
    controls/CustomEditableListBox.py
  • +1 -1
    controls/CustomGrid.py
  • +1 -1
    controls/CustomIntCtrl.py
  • +3 -3
    controls/CustomStyledTextCtrl.py
  • +3 -3
    controls/CustomTable.py
  • +1 -1
    controls/CustomToolTip.py
  • +2 -2
    controls/CustomTree.py
  • +13 -13
    controls/DebugVariablePanel/DebugVariableGraphicViewer.py
  • +1 -1
    controls/DebugVariablePanel/DebugVariableItem.py
  • +2 -2
    controls/DebugVariablePanel/DebugVariablePanel.py
  • +5 -5
    controls/DebugVariablePanel/DebugVariableTextViewer.py
  • +8 -8
    controls/DebugVariablePanel/DebugVariableViewer.py
  • +1 -1
    controls/DebugVariablePanel/GraphButton.py
  • +1 -1
    controls/DebugVariablePanel/RingBuffer.py
  • +1 -1
    controls/DebugVariablePanel/__init__.py
  • +3 -4
    controls/DiscoveryPanel.py
  • +1 -1
    controls/DurationCellEditor.py
  • +3 -3
    controls/EnhancedStatusBar.py
  • +4 -4
    controls/FolderTree.py
  • +1 -1
    controls/IDBrowser.py
  • +4 -6
    controls/LibraryPanel.py
  • +1 -1
    controls/LocationCellEditor.py
  • +6 -6
    controls/LogViewer.py
  • +2 -2
    controls/PouInstanceVariablesPanel.py
  • +4 -4
    controls/ProjectPropertiesPanel.py
  • +2 -2
    controls/SearchResultPanel.py
  • +1 -1
    controls/TextCtrlAutoComplete.py
  • +9 -9
    controls/VariablePanel.py
  • +1 -1
    controls/__init__.py
  • +3 -3
    dialogs/AboutDialog.py
  • +2 -2
    dialogs/ActionBlockDialog.py
  • +2 -2
    dialogs/ArrayTypeDialog.py
  • +2 -2
    dialogs/BlockPreviewDialog.py
  • +2 -2
    dialogs/BrowseLocationsDialog.py
  • +1 -1
    dialogs/BrowseValuesLibraryDialog.py
  • +1 -1
    dialogs/CommentEditDialog.py
  • +2 -2
    dialogs/ConnectionDialog.py
  • +2 -2
    dialogs/DurationEditorDialog.py
  • +3 -3
    dialogs/FBDBlockDialog.py
  • +5 -5
    dialogs/FBDVariableDialog.py
  • +1 -1
    dialogs/FindInPouDialog.py
  • +1 -1
    dialogs/ForceVariableDialog.py
  • +1 -1
    dialogs/IDManager.py
  • +1 -1
    dialogs/IDMergeDialog.py
  • +4 -4
    dialogs/LDElementDialog.py
  • +2 -2
    dialogs/LDPowerRailDialog.py
  • +1 -1
    dialogs/MessageBoxOnce.py
  • +2 -2
    dialogs/PouActionDialog.py
  • +2 -2
    dialogs/PouDialog.py
  • +1 -1
    dialogs/PouNameDialog.py
  • +2 -2
    dialogs/PouTransitionDialog.py
  • +1 -1
    dialogs/ProjectDialog.py
  • +2 -2
    dialogs/SFCDivergenceDialog.py
  • +4 -4
    dialogs/SFCStepDialog.py
  • +1 -1
    dialogs/SFCStepNameDialog.py
  • +5 -5
    dialogs/SFCTransitionDialog.py
  • +1 -1
    dialogs/SearchInProjectDialog.py
  • +1 -1
    dialogs/UriEditor.py
  • +1 -1
    dialogs/__init__.py
  • +1 -1
    docutil/__init__.py
  • +1 -1
    docutil/dochtml.py
  • +2 -2
    docutil/docpdf.py
  • +4 -4
    docutil/docsvg.py
  • +6 -6
    editors/CodeFileEditor.py
  • +2 -2
    editors/ConfTreeNodeEditor.py
  • +5 -5
    editors/DataTypeEditor.py
  • +3 -3
    editors/DebugViewer.py
  • +1 -1
    editors/EditorPanel.py
  • +1 -1
    editors/FileManagementPanel.py
  • +1 -1
    editors/IECCodeViewer.py
  • +6 -6
    editors/LDViewer.py
  • +1 -1
    editors/ProjectNodeEditor.py
  • +9 -9
    editors/ResourceEditor.py
  • +2 -2
    editors/SFCViewer.py
  • +10 -10
    editors/TextViewer.py
  • +80 -80
    editors/Viewer.py
  • +5 -5
    etherlab/ConfigEditor.py
  • +15 -15
    etherlab/EtherCATManagementEditor.py
  • +2 -2
    etherlab/EthercatCIA402Slave.py
  • +4 -4
    etherlab/EthercatMaster.py
  • +1 -1
    etherlab/EthercatSlave.py
  • +1 -1
    etherlab/__init__.py
  • +1 -1
    etherlab/runtime_etherlab.py
  • +2 -2
    graphics/DebugDataConsumer.py
  • +6 -6
    graphics/FBD_Objects.py
  • +15 -15
    graphics/GraphicCommons.py
  • +10 -10
    graphics/LD_Objects.py
  • +1 -1
    graphics/RubberBand.py
  • +10 -10
    graphics/SFC_Objects.py
  • +1 -1
    graphics/ToolTipProducer.py
  • +6 -6
    i18n/mki18n.py
  • +14 -14
    modbus/mb_utils.py
  • +9 -9
    modbus/modbus.py
  • +1 -1
    opc_ua/__init__.py
  • +2 -2
    opc_ua/client.py
  • +9 -9
    opc_ua/opcua_client_maker.py
  • +1 -1
    plcopen/BlockInstanceCollector.py
  • +1 -1
    plcopen/InstanceTagnameCollector.py
  • +1 -1
    plcopen/InstancesPathCollector.py
  • +1 -1
    plcopen/POUVariablesCollector.py
  • +1 -1
    plcopen/VariableInfoCollector.py
  • +2 -2
    plcopen/XSLTModelQuery.py
  • +1 -1
    plcopen/__init__.py
  • +1 -1
    plcopen/definitions.py
  • +9 -9
    plcopen/plcopen.py
  • +10 -10
    plcopen/structures.py
  • +5 -5
    plcopen/types_enums.py
  • +1 -1
    py_ext/PythonEditor.py
  • +3 -5
    py_ext/PythonFileCTNMixin.py
  • +1 -1
    py_ext/__init__.py
  • +1 -1
    py_ext/py_ext.py
  • +5 -5
    runtime/NevowServer.py
  • +4 -4
    runtime/PLCObject.py
  • +2 -2
    runtime/PyroServer.py
  • +2 -2
    runtime/ServicePublisher.py
  • +2 -2
    runtime/Stunnel.py
  • +8 -8
    runtime/WampClient.py
  • +1 -1
    runtime/Worker.py
  • +2 -2
    runtime/__init__.py
  • +2 -2
    runtime/monotonic_time.py
  • +2 -2
    runtime/spawn_subprocess.py
  • +2 -2
    runtime/typemapping.py
  • +1 -1
    runtime/xenomai.py
  • +1 -1
    svghmi/__init__.py
  • +6 -6
    svghmi/hmi_tree.py
  • +19 -19
    svghmi/i18n.py
  • +3 -3
    svghmi/svghmi.py
  • +2 -2
    svghmi/svghmi_server.py
  • +6 -10
    svghmi/ui.py
  • +1 -1
    targets/Generic/__init__.py
  • +1 -1
    targets/Linux/__init__.py
  • +1 -1
    targets/Win32/__init__.py
  • +1 -1
    targets/Xenomai/__init__.py
  • +3 -3
    targets/__init__.py
  • +8 -8
    targets/toolchain_gcc.py
  • +2 -2
    targets/toolchain_makefile.py
  • +1 -1
    tests/ide_tests/conftest.py
  • +2 -2
    tests/ide_tests/load_and_build_tests.pytest/test_application.py
  • +2 -2
    tests/ide_tests/wx_widgets.pytest/test_CustomIntCtrl.py
  • +1 -1
    util/BitmapLibrary.py
  • +3 -3
    util/ExceptionHandler.py
  • +1 -1
    util/MiniTextControler.py
  • +2 -3
    util/ProcessLogger.py
  • +1 -1
    util/TranslationCatalogs.py
  • +1 -1
    util/misc.py
  • +1 -1
    util/paths.py
  • +3 -3
    version.py
  • +1 -1
    wxglade_hmi/__init__.py
  • +1 -1
    wxglade_hmi/wxglade_hmi.py
  • +1 -1
    xmlclass/__init__.py
  • +28 -32
    xmlclass/xmlclass.py
  • +18 -18
    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()
    + kw = list(self.Variables.keys())
    else:
    - kw = self.Keywords + self.Variables.keys() + self.Functions.keys()
    + 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": {