Merged. Some changes that should already have been incuded during previous merge (mostly about PlcStatus) have been included this time.
authorEdouard Tisserant
Fri, 23 Nov 2018 12:13:24 +0100
changeset 2459 21164625b393
parent 2458 2a70d5240300 (current diff)
parent 2457 9deec258ab1a (diff)
child 2460 89abeece2c71
Merged. Some changes that should already have been incuded during previous merge (mostly about PlcStatus) have been included this time.
BeremizIDE.py
Beremiz_service.py
PLCGenerator.py
ProjectController.py
connectors/WAMP/__init__.py
controls/DiscoveryPanel.py
editors/ConfTreeNodeEditor.py
modbus/modbus.py
runtime/PLCObject.py
runtime/WampClient.py
--- a/Beremiz.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/Beremiz.py	Fri Nov 23 12:13:24 2018 +0100
@@ -28,6 +28,7 @@
 import os
 import sys
 import getopt
+from past.builtins import execfile
 
 import wx
 from wx.lib.agw.advancedsplash import AdvancedSplash, AS_NOTIMEOUT, AS_CENTER_ON_SCREEN
--- a/BeremizIDE.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/BeremizIDE.py	Fri Nov 23 12:13:24 2018 +0100
@@ -31,12 +31,11 @@
 import tempfile
 import shutil
 import random
-import types
 import time
 from time import time as gettime
 from threading import Lock, Timer, currentThread
 
-import cPickle
+from six.moves import cPickle, xrange
 import wx.lib.buttons
 import wx.lib.statbmp
 import wx.stc
@@ -718,7 +717,7 @@
 
     def GenerateMenuRecursive(self, items, menu):
         for kind, infos in items:
-            if isinstance(kind, types.ListType):
+            if isinstance(kind, list):
                 text, id = infos
                 submenu = wx.Menu('')
                 self.GenerateMenuRecursive(kind, submenu)
--- a/Beremiz_service.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/Beremiz_service.py	Fri Nov 23 12:13:24 2018 +0100
@@ -32,11 +32,15 @@
 import threading
 from threading import Thread, Semaphore, Lock
 import __builtin__
+from builtins import str as text
+from past.builtins import execfile
+from six.moves import builtins
 
 import runtime
 from runtime.PyroServer import Server
 from runtime.xenomai import TryPreloadXenomai
 from runtime import LogMessageAndException
+from runtime import PlcStatus
 import util.paths as paths
 
 
@@ -142,7 +146,7 @@
     WorkingDir = os.getcwd()
     argv = [WorkingDir]
 
-__builtin__.__dict__['_'] = lambda x: x
+builtins.__dict__['_'] = lambda x: x
 # TODO: add a cmdline parameter if Trying Preloading Xenomai makes problem
 TryPreloadXenomai()
 version()
@@ -161,12 +165,12 @@
     domain = "Beremiz"
 
     # Define locale for wx
-    loc = __builtin__.__dict__.get('loc', None)
+    loc = builtins.__dict__.get('loc', None)
     if loc is None:
         wx.LogGui.EnableLogging(False)
         loc = wx.Locale(langid)
         wx.LogGui.EnableLogging(True)
-        __builtin__.__dict__['loc'] = loc
+        builtins.__dict__['loc'] = loc
         # Define location for searching translation files
     loc.AddCatalogLookupPathPrefix(localedir)
     # Define locale domain
@@ -184,8 +188,8 @@
     def unicode_translation(message):
         return wx.GetTranslation(message).encode(default_locale)
 
-    __builtin__.__dict__['_'] = unicode_translation
-    # __builtin__.__dict__['_'] = wx.GetTranslation
+    builtins.__dict__['_'] = unicode_translation
+    # builtins.__dict__['_'] = wx.GetTranslation
 
 
 # Life is hard... have a candy.
@@ -200,7 +204,6 @@
 
     if havewx:
         import re
-        from types import *
 
         if wx.VERSION >= (3, 0, 0):
             app = wx.App(redirect=False)
@@ -315,7 +318,7 @@
                 ip_addr = self.pyroserver.ip_addr
                 ip_addr = '' if ip_addr is None else ip_addr
                 dlg = ParamsEntryDialog(None, _("Enter the IP of the interface to bind"), defaultValue=ip_addr)
-                dlg.SetTests([(re.compile('\d{1,3}(?:\.\d{1,3}){3}$').match, _("IP is not valid!")),
+                dlg.SetTests([(re.compile(r'\d{1,3}(?:\.\d{1,3}){3}$').match, _("IP is not valid!")),
                               (lambda x:len([x for x in x.split(".") if 0 <= int(x) <= 255]) == 4,
                                _("IP is not valid!"))])
                 if dlg.ShowModal() == wx.ID_OK:
@@ -324,7 +327,7 @@
 
             def OnTaskBarChangePort(self, evt):
                 dlg = ParamsEntryDialog(None, _("Enter a port number "), defaultValue=str(self.pyroserver.port))
-                dlg.SetTests([(UnicodeType.isdigit, _("Port number must be an integer!")), (lambda port: 0 <= int(port) <= 65535, _("Port number must be 0 <= port <= 65535!"))])
+                dlg.SetTests([(text.isdigit, _("Port number must be an integer!")), (lambda port: 0 <= int(port) <= 65535, _("Port number must be 0 <= port <= 65535!"))])
                 if dlg.ShowModal() == wx.ID_OK:
                     self.pyroserver.port = int(dlg.GetValue())
                     self.pyroserver.Restart()
@@ -368,9 +371,9 @@
                 wx.CallAfter(wx.GetApp().ExitMainLoop)
 
             def UpdateIcon(self, plcstatus):
-                if plcstatus is "Started":
+                if plcstatus is PlcStatus.Started:
                     currenticon = self.MakeIcon(starticon)
-                elif plcstatus is "Stopped":
+                elif plcstatus is PlcStatus.Stopped:
                     currenticon = self.MakeIcon(stopicon)
                 else:
                     currenticon = self.MakeIcon(defaulticon)
--- a/CodeFileTreeNode.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/CodeFileTreeNode.py	Fri Nov 23 12:13:24 2018 +0100
@@ -27,8 +27,9 @@
 import os
 import re
 import traceback
-
+from builtins import str as text
 from copy import deepcopy
+
 from lxml import etree
 from xmlclass import GenerateParserFromXSDstring
 
@@ -113,8 +114,8 @@
                 '<%s>' % self.CODEFILE_NAME,
                 '<%s xmlns:xhtml="http://www.w3.org/1999/xhtml">' % self.CODEFILE_NAME)
             for cre, repl in [
-                    (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
-                    (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
+                    (re.compile(r"(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
+                    (re.compile(r"(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
                 codefile_xml = cre.sub(repl, codefile_xml)
 
             try:
@@ -124,7 +125,7 @@
                     self.GetCTRoot().logger.write_warning(XSDSchemaErrorMessage.format(a1=fname, a2=lnum, a3=src))
                 self.CreateCodeFileBuffer(True)
             except Exception as exc:
-                msg = _("Couldn't load confnode parameters {a1} :\n {a2}").format(a1=self.CTNName(), a2=unicode(exc))
+                msg = _("Couldn't load confnode parameters {a1} :\n {a2}").format(a1=self.CTNName(), a2=text(exc))
                 self.GetCTRoot().logger.write_error(msg)
                 self.GetCTRoot().logger.write_error(traceback.format_exc())
                 raise Exception
--- a/ConfigTreeNode.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/ConfigTreeNode.py	Fri Nov 23 12:13:24 2018 +0100
@@ -36,10 +36,12 @@
 import traceback
 import types
 import shutil
+from builtins import str as text
+from past.builtins import execfile
+
 from lxml import etree
 
 from xmlclass import GenerateParserFromXSDstring
-
 from PLCControler import LOCATION_CONFNODE
 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
 
@@ -277,7 +279,7 @@
         LDFLAGS = []
         if CTNLDFLAGS is not None:
             # LDFLAGS can be either string
-            if isinstance(CTNLDFLAGS, (str, unicode)):
+            if isinstance(CTNLDFLAGS, (str, text)):
                 LDFLAGS += [CTNLDFLAGS]
             # or list of strings
             elif isinstance(CTNLDFLAGS, list):
@@ -627,7 +629,7 @@
                 self.MandatoryParams = ("BaseParams", self.BaseParams)
                 basexmlfile.close()
             except Exception as exc:
-                msg = _("Couldn't load confnode base parameters {a1} :\n {a2}").format(a1=ConfNodeName, a2=unicode(exc))
+                msg = _("Couldn't load confnode base parameters {a1} :\n {a2}").format(a1=ConfNodeName, a2=text(exc))
                 self.GetCTRoot().logger.write_error(msg)
                 self.GetCTRoot().logger.write_error(traceback.format_exc())
 
@@ -644,7 +646,7 @@
                 self.CTNParams = (name, obj)
                 xmlfile.close()
             except Exception as exc:
-                msg = _("Couldn't load confnode parameters {a1} :\n {a2}").format(a1=ConfNodeName, a2=unicode(exc))
+                msg = _("Couldn't load confnode parameters {a1} :\n {a2}").format(a1=ConfNodeName, a2=text(exc))
                 self.GetCTRoot().logger.write_error(msg)
                 self.GetCTRoot().logger.write_error(traceback.format_exc())
 
@@ -657,6 +659,6 @@
                 try:
                     self.CTNAddChild(pname, ptype)
                 except Exception as exc:
-                    msg = _("Could not add child \"{a1}\", type {a2} :\n{a3}\n").format(a1=pname, a2=ptype, a3=unicode(exc))
+                    msg = _("Could not add child \"{a1}\", type {a2} :\n{a3}\n").format(a1=pname, a2=ptype, a3=text(exc))
                     self.GetCTRoot().logger.write_error(msg)
                     self.GetCTRoot().logger.write_error(traceback.format_exc())
--- a/IDEFrame.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/IDEFrame.py	Fri Nov 23 12:13:24 2018 +0100
@@ -23,14 +23,17 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 from __future__ import absolute_import
+from __future__ import division
 import sys
-import cPickle
-from types import TupleType
 import base64
+from future.builtins import \
+    round, \
+    str as text
 
 import wx
 import wx.grid
 import wx.aui
+from six.moves import cPickle, xrange
 
 from editors.EditorPanel import EditorPanel
 from editors.SFCViewer import SFC_Viewer
@@ -108,7 +111,7 @@
 def DecodeFileSystemPath(path, is_base64=True):
     if is_base64:
         path = base64.decodestring(path)
-    return unicode(path, sys.getfilesystemencoding())
+    return text(path, sys.getfilesystemencoding())
 
 
 def AppendMenu(parent, help, id, kind, text):
@@ -200,22 +203,22 @@
             raise ValueError("Not possible")
         if tab["size"][0] == rect.width:
             if tab["pos"][1] == rect.y:
-                split = (wx.TOP, float(tab["size"][1]) / float(rect.height))
+                split = (wx.TOP, tab["size"][1] / rect.height)
                 split_rect = wx.Rect(rect.x, rect.y + tab["size"][1] + TAB_BORDER,
                                      rect.width, rect.height - tab["size"][1] - TAB_BORDER)
             elif tab["pos"][1] == rect.height + 1 - tab["size"][1]:
-                split = (wx.BOTTOM, 1.0 - float(tab["size"][1]) / float(rect.height))
+                split = (wx.BOTTOM, 1.0 - tab["size"][1] / rect.height)
                 split_rect = wx.Rect(rect.x, rect.y,
                                      rect.width, rect.height - tab["size"][1] - TAB_BORDER)
             split_id = idx
             break
         elif tab["size"][1] == rect.height:
             if tab["pos"][0] == rect.x:
-                split = (wx.LEFT, float(tab["size"][0]) / float(rect.width))
+                split = (wx.LEFT, tab["size"][0] / rect.width)
                 split_rect = wx.Rect(rect.x + tab["size"][0] + TAB_BORDER, rect.y,
                                      rect.width - tab["size"][0] - TAB_BORDER, rect.height)
             elif tab["pos"][0] == rect.width + 1 - tab["size"][0]:
-                split = (wx.RIGHT, 1.0 - float(tab["size"][0]) / float(rect.width))
+                split = (wx.RIGHT, 1.0 - tab["size"][0] / rect.width)
                 split_rect = wx.Rect(rect.x, rect.y,
                                      rect.width - tab["size"][0] - TAB_BORDER, rect.height)
             split_id = idx
@@ -833,7 +836,7 @@
         return None
 
     def LoadTabLayout(self, notebook, tabs, mode="all", first_index=None):
-        if isinstance(tabs, ListType):
+        if isinstance(tabs, list):
             if len(tabs) == 0:
                 return
             raise ValueError("Not supported")
@@ -2435,7 +2438,7 @@
 
         result = self.Controler.PastePou(pou_type, pou_xml)
 
-        if not isinstance(result, TupleType):
+        if not isinstance(result, tuple):
             self.ShowErrorMessage(result)
         else:
             self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
@@ -2591,7 +2594,7 @@
 
 
 def UPPER_DIV(x, y):
-    return (x / y) + {True: 0, False: 1}[(x % y) == 0]
+    return (x // y) + {True: 0, False: 1}[(x % y) == 0]
 
 
 class GraphicPrintout(wx.Printout):
@@ -2638,8 +2641,8 @@
         ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
         pw, ph = self.GetPageSizePixels()
         dw, dh = dc.GetSizeTuple()
-        Xscale = (float(dw) * float(ppiPrinterX)) / (float(pw) * 25.4)
-        Yscale = (float(dh) * float(ppiPrinterY)) / (float(ph) * 25.4)
+        Xscale = (dw * ppiPrinterX) / (pw * 25.4)
+        Yscale = (dh * ppiPrinterY) / (ph * 25.4)
 
         fontsize = self.FontSize * Yscale
 
@@ -2661,10 +2664,10 @@
 
         # Calculate the position on the DC for centering the graphic
         posX = area_width * ((page - 1) % self.PageGrid[0])
-        posY = area_height * ((page - 1) / self.PageGrid[0])
-
-        scaleX = float(area_width) / float(self.PageSize[0])
-        scaleY = float(area_height) / float(self.PageSize[1])
+        posY = area_height * ((page - 1) // self.PageGrid[0])
+
+        scaleX = area_width / self.PageSize[0]
+        scaleY = area_height / self.PageSize[1]
         scale = min(scaleX, scaleY)
 
         # Set the scale and origin
--- a/PLCControler.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/PLCControler.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,12 +25,14 @@
 
 
 from __future__ import absolute_import
-from types import TupleType
+from __future__ import division
 from copy import deepcopy
 import os
 import re
 import datetime
 from time import localtime
+from functools import reduce
+from future.builtins import round
 
 import util.paths as paths
 from plcopen import *
@@ -43,8 +45,8 @@
 from graphics.GraphicCommons import *
 from PLCGenerator import *
 
-duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:\.[0-9]*)?)ms)?")
-VARIABLE_NAME_SUFFIX_MODEL = re.compile('(\d+)$')
+duration_model = re.compile(r"(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:\.[0-9]*)?)ms)?")
+VARIABLE_NAME_SUFFIX_MODEL = re.compile(r'(\d+)$')
 
 ScriptDirectory = paths.AbsDir(__file__)
 
@@ -461,7 +463,7 @@
                     self.ProgramFilePath = filepath
                 return program_text, errors, warnings
             except PLCGenException as ex:
-                errors.append(ex.message)
+                errors.append(str(ex))
         else:
             errors.append("No project opened")
         return "", errors, warnings
@@ -873,7 +875,7 @@
             tempvar.setname(var.Name)
 
             var_type = PLCOpenParser.CreateElement("type", "variable")
-            if isinstance(var.Type, TupleType):
+            if isinstance(var.Type, tuple):
                 if var.Type[0] == "array":
                     _array_type, base_type_name, dimensions = var.Type
                     array = PLCOpenParser.CreateElement("array", "dataType")
@@ -1366,7 +1368,7 @@
         return True
 
     def IsLocatableType(self, typename, debug=False):
-        if isinstance(typename, TupleType) or self.GetBlockType(typename) is not None:
+        if isinstance(typename, tuple) or self.GetBlockType(typename) is not None:
             return False
 
         # the size of these types is implementation dependend
@@ -1379,7 +1381,7 @@
         return True
 
     def IsEnumeratedType(self, typename, debug=False):
-        if isinstance(typename, TupleType):
+        if isinstance(typename, tuple):
             typename = typename[1]
         datatype = self.GetDataType(typename, debug)
         if datatype is not None:
@@ -1393,7 +1395,7 @@
     def IsSubrangeType(self, typename, exclude=None, debug=False):
         if typename == exclude:
             return False
-        if isinstance(typename, TupleType):
+        if isinstance(typename, tuple):
             typename = typename[1]
         datatype = self.GetDataType(typename, debug)
         if datatype is not None:
@@ -1612,7 +1614,7 @@
                     element = PLCOpenParser.CreateElement("variable", "struct")
                     element.setname(element_infos["Name"])
                     element_type = PLCOpenParser.CreateElement("type", "variable")
-                    if isinstance(element_infos["Type"], TupleType):
+                    if isinstance(element_infos["Type"], tuple):
                         if element_infos["Type"][0] == "array":
                             _array_type, base_type_name, dimensions = element_infos["Type"]
                             array = PLCOpenParser.CreateElement("array", "dataType")
@@ -1939,8 +1941,8 @@
 
             x, y, width, height = bbox.bounding_box()
             if middle:
-                new_pos[0] -= width / 2
-                new_pos[1] -= height / 2
+                new_pos[0] -= width // 2
+                new_pos[1] -= height // 2
             else:
                 new_pos = map(lambda x: x + 30, new_pos)
             if scaling[0] != 0 and scaling[1] != 0:
--- a/PLCGenerator.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/PLCGenerator.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,8 +24,10 @@
 
 
 from __future__ import absolute_import
-from types import *
 import re
+from functools import reduce
+from six.moves import xrange
+
 from plcopen import PLCOpenParser
 from plcopen.structures import *
 from plcopen.types_enums import *
@@ -708,7 +710,7 @@
 
     def ComputeConnectionTypes(self, pou):
         body = pou.getbody()
-        if isinstance(body, ListType):
+        if isinstance(body, list):
             body = body[0]
         body_content = body.getcontent()
         body_type = body_content.getLocalTag()
@@ -941,7 +943,7 @@
 
     def ComputeProgram(self, pou):
         body = pou.getbody()
-        if isinstance(body, ListType):
+        if isinstance(body, list):
             body = body[0]
         body_content = body.getcontent()
         body_type = body_content.getLocalTag()
@@ -1025,7 +1027,7 @@
                     try:
                         self.GenerateBlock(instance, block_infos, body, None)
                     except ValueError as e:
-                        raise PLCGenException(e.message)
+                        raise PLCGenException(str(e))
                 elif isinstance(instance, ConnectorClass):
                     connector = instance.getname()
                     if self.ComputedConnectors.get(connector, None):
@@ -1049,7 +1051,7 @@
         uncomputed_index = range(len(paths))
         factorized_paths = []
         for num, path in enumerate(paths):
-            if isinstance(path, ListType):
+            if isinstance(path, list):
                 if len(path) > 1:
                     str_path = str(path[-1:])
                     same_paths.setdefault(str_path, [])
@@ -1303,7 +1305,7 @@
                 try:
                     paths.append(str(self.GenerateBlock(next, block_infos, body, connection, order, to_inout)))
                 except ValueError as e:
-                    raise PLCGenException(e.message)
+                    raise PLCGenException(str(e))
             elif isinstance(next, ContinuationClass):
                 name = next.getname()
                 computed_value = self.ComputedConnectors.get(name, None)
@@ -1339,7 +1341,7 @@
                         paths.append([variable, tuple(factorized_paths)])
                     else:
                         paths.append([variable] + factorized_paths)
-                elif isinstance(result[0], ListType):
+                elif isinstance(result[0], list):
                     paths.append([variable] + result[0])
                 elif result[0] is not None:
                     paths.append([variable, result[0]])
@@ -1350,7 +1352,7 @@
         return paths
 
     def ComputePaths(self, paths, first=False):
-        if isinstance(paths, TupleType):
+        if isinstance(paths, tuple):
             if None in paths:
                 return [("TRUE", ())]
             else:
@@ -1359,7 +1361,7 @@
                     return JoinList([(" OR ", ())], vars)
                 else:
                     return [("(", ())] + JoinList([(" OR ", ())], vars) + [(")", ())]
-        elif isinstance(paths, ListType):
+        elif isinstance(paths, list):
             vars = [self.ComputePaths(path) for path in paths]
             return JoinList([(" AND ", ())], vars)
         elif paths is None:
@@ -1421,7 +1423,7 @@
             if connections is not None and len(connections) == 1:
                 instanceLocalId = connections[0].getrefLocalId()
                 body = pou.getbody()
-                if isinstance(body, ListType):
+                if isinstance(body, list):
                     body = body[0]
                 return body.getcontentInstance(instanceLocalId)
         return None
@@ -1433,7 +1435,7 @@
             if connections is not None and len(connections) == 1:
                 instanceLocalId = connections[0].getrefLocalId()
                 body = pou.getbody()
-                if isinstance(body, ListType):
+                if isinstance(body, list):
                     body = body[0]
                 instances.append(body.getcontentInstance(instanceLocalId))
         return instances
@@ -1454,7 +1456,7 @@
                 if connections is not None and len(connections) == 1:
                     instanceLocalId = connections[0].getrefLocalId()
                     body = pou.getbody()
-                    if isinstance(body, ListType):
+                    if isinstance(body, list):
                         body = body[0]
                     instance = body.getcontentInstance(instanceLocalId)
                     if isinstance(instance, TransitionClass):
@@ -1488,7 +1490,7 @@
             if connections is not None and len(connections) == 1:
                 instanceLocalId = connections[0].getrefLocalId()
                 body = pou.getbody()
-                if isinstance(body, ListType):
+                if isinstance(body, list):
                     body = body[0]
                 instance = body.getcontentInstance(instanceLocalId)
                 if isinstance(instance, TransitionClass):
@@ -1513,7 +1515,7 @@
         if connections is not None and len(connections) == 1:
             stepLocalId = connections[0].getrefLocalId()
             body = pou.getbody()
-            if isinstance(body, ListType):
+            if isinstance(body, list):
                 body = body[0]
             step = body.getcontentInstance(stepLocalId)
             self.GenerateSFCStep(step, pou)
@@ -1560,7 +1562,7 @@
             if connections is not None and len(connections) == 1:
                 instanceLocalId = connections[0].getrefLocalId()
                 body = pou.getbody()
-                if isinstance(body, ListType):
+                if isinstance(body, list):
                     body = body[0]
                 instance = body.getcontentInstance(instanceLocalId)
                 if isinstance(instance, StepClass):
@@ -1615,7 +1617,7 @@
                 self.TagName = previous_tagname
             elif transitionValues["type"] == "connection":
                 body = pou.getbody()
-                if isinstance(body, ListType):
+                if isinstance(body, list):
                     body = body[0]
                 connections = transitionValues["value"].getconnections()
                 if connections is not None:
--- a/ProjectController.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/ProjectController.py	Fri Nov 23 12:13:24 2018 +0100
@@ -36,11 +36,11 @@
 import shutil
 import re
 import tempfile
-from types import ListType
 from threading import Timer
 from datetime import datetime
 from weakref import WeakKeyDictionary
-from itertools import izip
+from functools import reduce
+from six.moves import xrange
 
 import wx
 
@@ -67,13 +67,13 @@
 base_folder = paths.AbsParentDir(__file__)
 
 MATIEC_ERROR_MODEL = re.compile(
-    ".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): (?:error)|(?:warning) : (.*)$")
+    r".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): (?:error)|(?:warning) : (.*)$")
 
 
 def ExtractChildrenTypesFromCatalog(catalog):
     children_types = []
     for n, d, _h, c in catalog:
-        if isinstance(c, ListType):
+        if isinstance(c, list):
             children_types.extend(ExtractChildrenTypesFromCatalog(c))
         else:
             children_types.append((n, GetClassImporter(c), d))
@@ -83,7 +83,7 @@
 def ExtractMenuItemsFromCatalog(catalog):
     menu_items = []
     for n, d, h, c in catalog:
-        if isinstance(c, ListType):
+        if isinstance(c, list):
             children = ExtractMenuItemsFromCatalog(c)
         else:
             children = []
@@ -712,7 +712,7 @@
             lines = [line.strip() for line in location_file.readlines()]
             # This regular expression parses the lines genereated by IEC2C
             LOCATED_MODEL = re.compile(
-                "__LOCATED_VAR\((?P<IEC_TYPE>[A-Z]*),(?P<NAME>[_A-Za-z0-9]*),(?P<DIR>[QMI])(?:,(?P<SIZE>[XBWDL]))?,(?P<LOC>[,0-9]*)\)")
+                r"__LOCATED_VAR\((?P<IEC_TYPE>[A-Z]*),(?P<NAME>[_A-Za-z0-9]*),(?P<DIR>[QMI])(?:,(?P<SIZE>[XBWDL]))?,(?P<LOC>[,0-9]*)\)")
             for line in lines:
                 # If line match RE,
                 result = LOCATED_MODEL.match(line)
@@ -770,7 +770,7 @@
         plc_file.close()
         plc_file = open(self._getIECcodepath(), "r")
         self.ProgramOffset = 0
-        for dummy in plc_file.xreadlines():
+        for dummy in plc_file.readlines():
             self.ProgramOffset += 1
         plc_file.close()
         plc_file = open(self._getIECcodepath(), "a")
@@ -858,9 +858,9 @@
         H_files = map(
             lambda filename: os.path.join(buildpath, filename), H_files)
         for H_file in H_files:
-            with file(H_file, 'r') as original:
+            with open(H_file, 'r') as original:
                 data = original.read()
-            with file(H_file, 'w') as modified:
+            with open(H_file, 'w') as modified:
                 modified.write('#include "beremiz.h"\n' + data)
 
         self.logger.write(_("Extracting Located Variables...\n"))
@@ -952,7 +952,7 @@
 
                 # Separate sections
                 ListGroup = []
-                for line in open(csvfile, 'r').xreadlines():
+                for line in open(csvfile, 'r').readlines():
                     strippedline = line.strip()
                     if strippedline.startswith("//"):
                         # Start new section
@@ -1293,7 +1293,7 @@
                 self._IECCodeView.SetTextSyntax("ALL")
                 self._IECCodeView.SetKeywords(IEC_KEYWORDS)
                 try:
-                    text = file(plc_file).read()
+                    text = open(plc_file).read()
                 except Exception:
                     text = '(* No IEC code have been generated at that time ! *)'
                 self._IECCodeView.SetText(text=text)
@@ -1503,7 +1503,7 @@
                         debug_vars = UnpackDebugBuffer(
                             debug_buff, self.TracedIECTypes)
                         if debug_vars is not None and len(debug_vars) == len(self.TracedIECPath):
-                            for IECPath, values_buffer, value in izip(
+                            for IECPath, values_buffer, value in zip(
                                     self.TracedIECPath,
                                     self.DebugValuesBuffers,
                                     debug_vars):
@@ -1682,7 +1682,7 @@
         debug_ticks, buffers = self.SnapshotAndResetDebugValuesBuffers()
         start_time = time.time()
         if len(self.TracedIECPath) == len(buffers):
-            for IECPath, values in izip(self.TracedIECPath, buffers):
+            for IECPath, values in zip(self.TracedIECPath, buffers):
                 if len(values) > 0:
                     self.CallWeakcallables(
                         IECPath, "NewValues", debug_ticks, values)
--- a/canfestival/canfestival.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/canfestival/canfestival.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,6 +24,7 @@
 # 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
@@ -327,7 +328,7 @@
             nodeid = self.CanFestivalNode.getNodeId()
             if value != nodeid:
                 slaves = self.GetSlaveIDs()
-                dir = (value - nodeid) / abs(value - nodeid)
+                dir = (value - nodeid) // abs(value - nodeid)
                 while value in slaves and value >= 0:
                     value += dir
                 if value < 0:
@@ -616,6 +617,6 @@
         if can_driver is not None:
             can_driver_path = os.path.join(CanFestivalPath, "drivers", can_driver, can_driver_name)
             if os.path.exists(can_driver_path):
-                res += ((can_driver_name, file(can_driver_path, "rb")),)
+                res += ((can_driver_name, open(can_driver_path, "rb")),)
 
         return res
--- a/canfestival/config_utils.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/canfestival/config_utils.py	Fri Nov 23 12:13:24 2018 +0100
@@ -28,7 +28,7 @@
 import os
 import sys
 import getopt
-from types import *
+from past.builtins import long
 
 # Translation between IEC types and Can Open types
 IECToCOType = {
@@ -465,7 +465,7 @@
 
                 # Indicate that this PDO entry must be saved
                 if locationinfos["bit"] is not None:
-                    if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType):
+                    if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], list):
                         self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex]
                     if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]):
                         self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name)
@@ -557,7 +557,7 @@
 
             mapping = []
             for item in pdo_infos["mapping"]:
-                if isinstance(item, ListType):
+                if isinstance(item, list):
                     mapping.extend(item)
                 else:
                     mapping.append(item)
@@ -572,7 +572,7 @@
                     continue
                 new_index = False
 
-                if isinstance(variable, (IntType, LongType)):
+                if isinstance(variable, (int, long)):
                     # If variable is an integer then variable is unexpected
                     self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
                 else:
--- a/connectors/WAMP/__init__.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/connectors/WAMP/__init__.py	Fri Nov 23 12:13:24 2018 +0100
@@ -28,6 +28,7 @@
 import sys
 import traceback
 from threading import Thread, Event
+from builtins import str as text
 
 from twisted.internet import reactor, threads
 from autobahn.twisted import wamp
@@ -83,7 +84,7 @@
 
         # create a WAMP application session factory
         component_config = types.ComponentConfig(
-            realm=unicode(realm),
+            realm=text(realm),
             extra={"ID": ID})
         session_factory = wamp.ApplicationSessionFactory(
             config=component_config)
@@ -109,7 +110,7 @@
         reactor.run(installSignalHandlers=False)
 
     def WampSessionProcMapper(funcname):
-        wampfuncname = unicode('.'.join((ID, funcname)))
+        wampfuncname = text('.'.join((ID, funcname)))
 
         def catcher_func(*args, **kwargs):
             if _WampSession is not None:
--- a/controls/CustomStyledTextCtrl.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/CustomStyledTextCtrl.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,8 +24,10 @@
 
 
 from __future__ import absolute_import
+from functools import reduce
 import wx
 import wx.stc
+from six.moves import xrange
 
 if wx.Platform == '__WXMSW__':
     faces = {
--- a/controls/CustomTree.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/CustomTree.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,6 +24,7 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import wx
 import wx.lib.agw.customtreectrl as CT
 
@@ -100,14 +101,14 @@
         if self.BackgroundAlign & wx.ALIGN_RIGHT:
             x = client_size[0] - bitmap_size[0]
         elif self.BackgroundAlign & wx.ALIGN_CENTER_HORIZONTAL:
-            x = (client_size[0] - bitmap_size[0]) / 2
+            x = (client_size[0] - bitmap_size[0]) // 2
         else:
             x = 0
 
         if self.BackgroundAlign & wx.ALIGN_BOTTOM:
             y = client_size[1] - bitmap_size[1]
         elif self.BackgroundAlign & wx.ALIGN_CENTER_VERTICAL:
-            y = (client_size[1] - bitmap_size[1]) / 2
+            y = (client_size[1] - bitmap_size[1]) // 2
         else:
             y = 0
 
--- a/controls/DebugVariablePanel/DebugVariableGraphicViewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/DebugVariablePanel/DebugVariableGraphicViewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,7 @@
 
 
 from __future__ import absolute_import
-from types import TupleType
+from __future__ import division
 from time import time as gettime
 from cycler import cycler
 
@@ -36,6 +36,7 @@
 from matplotlib.backends.backend_wxagg import _convert_agg_to_wx_bitmap
 from matplotlib.backends.backend_agg import FigureCanvasAgg
 from mpl_toolkits.mplot3d import Axes3D
+from six.moves import xrange
 
 from editors.DebugViewer import REFRESH_PERIOD
 from controls.DebugVariablePanel.DebugVariableViewer import *
@@ -156,7 +157,7 @@
         # Check that data is valid regarding DebugVariablePanel
         try:
             values = eval(data)
-            if not isinstance(values, TupleType):
+            if not isinstance(values, tuple):
                 raise ValueError
         except Exception:
             message = _("Invalid value \"%s\" for debug variable") % data
@@ -194,7 +195,7 @@
 
                 # Get Before which Viewer the variable has to be moved or added
                 # according to the position of mouse in Viewer.
-                if y > height / 2:
+                if y > height // 2:
                     target_idx += 1
 
                 # Drag'n Drop is an internal is an internal move inside Debug
@@ -442,10 +443,10 @@
                 x = rect.x + (- w - offset
                               if direction == wx.LEFT
                               else rect.width + offset)
-                y = rect.y + (rect.height - h) / 2
+                y = rect.y + (rect.height - h) // 2
                 offset += w
             else:
-                x = rect.x + (rect.width - w) / 2
+                x = rect.x + (rect.width - w) // 2
                 y = rect.y + (- h - offset
                               if direction == wx.TOP
                               else rect.height + offset)
@@ -800,7 +801,7 @@
                 self.ParentWindow.SetCanvasPosition(
                     self.StartCursorTick +
                     (self.MouseStartPos.x - event.x) *
-                    (end_tick - start_tick) / rect.width)
+                    (end_tick - start_tick) // rect.width)
 
     def OnCanvasScroll(self, event):
         """
@@ -818,7 +819,7 @@
                 tick = (start_tick + end_tick) / 2.
             else:
                 tick = event.xdata
-            self.ParentWindow.ChangeRange(int(-event.step) / 3, tick)
+            self.ParentWindow.ChangeRange(int(-event.step) // 3, tick)
 
             # Vetoing event to prevent parent panel to be scrolled
             self.ParentWindow.VetoScrollEvent = True
@@ -926,7 +927,7 @@
         # Mouse is over Viewer figure and graph is not 3D
         bbox = self.GetAxesBoundingBox()
         if bbox.InsideXY(x, y) and not self.Is3DCanvas():
-            rect = wx.Rect(bbox.x, bbox.y, bbox.width / 2, bbox.height)
+            rect = wx.Rect(bbox.x, bbox.y, bbox.width // 2, bbox.height)
             # Mouse is over Viewer left part of figure
             if rect.InsideXY(x, y):
                 self.SetHighlight(HIGHLIGHT_LEFT)
@@ -936,7 +937,7 @@
                 self.SetHighlight(HIGHLIGHT_RIGHT)
 
         # Mouse is over upper part of Viewer
-        elif y < height / 2:
+        elif y < height // 2:
             # Viewer is upper one in Debug Variable Panel, show highlight
             if self.ParentWindow.IsViewerFirst(self):
                 self.SetHighlight(HIGHLIGHT_BEFORE)
@@ -1324,11 +1325,11 @@
         # Get value and forced flag for each variable displayed in graph
         # If cursor tick is not defined get value and flag of last received
         # or get value and flag of variable at cursor tick
-        values, forced = apply(zip, [(
+        args = [(
             item.GetValue(self.CursorTick)
             if self.CursorTick is not None
-            else (item.GetValue(), item.IsForced())
-        ) for item in self.Items])
+            else (item.GetValue(), item.IsForced())) for item in self.Items]
+        values, forced = zip(*args)
 
         # Get path of each variable displayed simplified using panel variable
         # name mask
@@ -1399,11 +1400,11 @@
             destGC.SetPen(HIGHLIGHT['DROP_PEN'])
             destGC.SetBrush(HIGHLIGHT['DROP_BRUSH'])
 
-            x_offset = (bbox.width / 2
+            x_offset = (bbox.width // 2
                         if self.Highlight == HIGHLIGHT_RIGHT
                         else 0)
             destGC.DrawRectangle(bbox.x + x_offset, bbox.y,
-                                 bbox.width / 2, bbox.height)
+                                 bbox.width // 2, bbox.height)
 
         # Draw other Viewer common elements
         self.DrawCommonElements(destGC, self.GetButtons())
--- a/controls/DebugVariablePanel/DebugVariablePanel.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/DebugVariablePanel/DebugVariablePanel.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,8 @@
 
 
 from __future__ import absolute_import
-from types import TupleType
+from __future__ import division
+from functools import reduce
 import numpy
 
 import wx
@@ -123,7 +124,7 @@
         # Check that data is valid regarding DebugVariablePanel
         try:
             values = eval(data)
-            if not isinstance(values, TupleType):
+            if not isinstance(values, tuple):
                 raise ValueError
         except Exception:
             message = _("Invalid value \"%s\" for debug variable") % data
@@ -307,7 +308,7 @@
 
         # Calculate range to apply to data
         self.CurrentRange = self.RANGE_VALUES[
-            self.CanvasRange.GetSelection()][1] / self.Ticktime
+            self.CanvasRange.GetSelection()][1] // self.Ticktime
 
     def SetDataProducer(self, producer):
         """
@@ -390,7 +391,7 @@
             cursor_tick_idx = numpy.argmin(numpy.abs(self.Ticks - cursor_tick))
             if self.Ticks[cursor_tick_idx] == self.CursorTick:
                 cursor_tick_idx = max(0,
-                                      min(cursor_tick_idx + abs(move) / move,
+                                      min(cursor_tick_idx + abs(move) // move,
                                           len(self.Ticks) - 1))
             self.CursorTick = self.Ticks[cursor_tick_idx]
             self.StartTick = max(
@@ -488,18 +489,18 @@
                 panel.ShowButtons(True)
                 merge_type = GRAPH_PARALLEL
                 if isinstance(panel, DebugVariableTextViewer) or panel.Is3DCanvas():
-                    if y_mouse > yw + height / 2:
+                    if y_mouse > yw + height // 2:
                         idx += 1
                     wx.CallAfter(self.MoveValue, variable, idx, True)
                 else:
                     rect = panel.GetAxesBoundingBox(True)
                     if rect.InsideXY(x_mouse, y_mouse):
-                        merge_rect = wx.Rect(rect.x, rect.y, rect.width / 2., rect.height)
+                        merge_rect = wx.Rect(rect.x, rect.y, rect.width // 2, rect.height)
                         if merge_rect.InsideXY(x_mouse, y_mouse):
                             merge_type = GRAPH_ORTHOGONAL
                         wx.CallAfter(self.MergeGraphs, variable, idx, merge_type, force=True)
                     else:
-                        if y_mouse > yw + height / 2:
+                        if y_mouse > yw + height // 2:
                             idx += 1
                         wx.CallAfter(self.MoveValue, variable, idx, True)
                 self.ForceRefresh()
@@ -547,16 +548,16 @@
             tick_duration = int(tick * self.Ticktime)
             not_null = False
             duration = ""
-            for value, format in [(tick_duration / DAY, _("%dd")),
-                                  ((tick_duration % DAY) / HOUR, _("%dh")),
-                                  ((tick_duration % HOUR) / MINUTE, _("%dm")),
-                                  ((tick_duration % MINUTE) / SECOND, _("%ds"))]:
+            for value, format in [(tick_duration // DAY, _("%dd")),
+                                  ((tick_duration % DAY) // HOUR, _("%dh")),
+                                  ((tick_duration % HOUR) // MINUTE, _("%dm")),
+                                  ((tick_duration % MINUTE) // SECOND, _("%ds"))]:
 
                 if value > 0 or not_null:
                     duration += format % value
                     not_null = True
 
-            duration += _("%03gms") % (float(tick_duration % SECOND) / MILLISECOND)
+            duration += _("%03gms") % ((tick_duration % SECOND) / MILLISECOND)
             self.TickTimeLabel.SetLabel("t: %s" % duration)
         else:
             self.TickLabel.SetLabel("")
@@ -638,7 +639,7 @@
 
     def OnRangeChanged(self, event):
         try:
-            self.CurrentRange = self.RANGE_VALUES[self.CanvasRange.GetSelection()][1] / self.Ticktime
+            self.CurrentRange = self.RANGE_VALUES[self.CanvasRange.GetSelection()][1] // self.Ticktime
         except ValueError:
             self.CanvasRange.SetValue(str(self.CurrentRange))
         wx.CallAfter(self.RefreshRange)
@@ -909,11 +910,12 @@
         xstart, ystart = self.GraphicsWindow.GetViewStart()
         window_size = self.GraphicsWindow.GetClientSize()
         vwidth, vheight = self.GraphicsSizer.GetMinSize()
-        posx = max(0, min(xstart, (vwidth - window_size[0]) / SCROLLBAR_UNIT))
-        posy = max(0, min(ystart, (vheight - window_size[1]) / SCROLLBAR_UNIT))
+        posx = max(0, min(xstart, (vwidth - window_size[0]) // SCROLLBAR_UNIT))
+        posy = max(0, min(ystart, (vheight - window_size[1]) // SCROLLBAR_UNIT))
         self.GraphicsWindow.Scroll(posx, posy)
         self.GraphicsWindow.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
-                                          vwidth / SCROLLBAR_UNIT, vheight / SCROLLBAR_UNIT,
+                                          vwidth // SCROLLBAR_UNIT,
+                                          vheight // SCROLLBAR_UNIT,
                                           posx, posy)
 
     def OnGraphicsWindowEraseBackground(self, event):
--- a/controls/DebugVariablePanel/DebugVariableTextViewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/DebugVariablePanel/DebugVariableTextViewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,7 @@
 
 
 from __future__ import absolute_import
-from types import TupleType
+from __future__ import division
 
 import wx
 
@@ -87,7 +87,7 @@
         # Check that data is valid regarding DebugVariablePanel
         try:
             values = eval(data)
-            if not isinstance(values, TupleType):
+            if not isinstance(values, tuple):
                 raise ValueError
         except Exception:
             message = _("Invalid value \"%s\" for debug variable") % data
@@ -104,7 +104,7 @@
             # according to the position of mouse in Viewer.
             _width, height = self.ParentControl.GetSize()
             target_idx = self.ParentControl.GetIndex()
-            if y > height / 2:
+            if y > height // 2:
                 target_idx += 1
 
             # Drag'n Drop is an internal is an internal move inside Debug
@@ -209,7 +209,7 @@
 
         # Draw item variable path at Viewer left side
         w, h = gc.GetTextExtent(item_path)
-        gc.DrawText(item_path, 20, (height - h) / 2)
+        gc.DrawText(item_path, 20, (height - h) // 2)
 
         # Update 'Release' button state and text color according to item forced
         # flag value
@@ -222,7 +222,7 @@
         # Draw item current value at right side of Viewer
         item_value = item.GetValue()
         w, h = gc.GetTextExtent(item_value)
-        gc.DrawText(item_value, width - 40 - w, (height - h) / 2)
+        gc.DrawText(item_value, width - 40 - w, (height - h) // 2)
 
         # Draw other Viewer common elements
         self.DrawCommonElements(gc)
--- a/controls/DebugVariablePanel/DebugVariableViewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/DebugVariablePanel/DebugVariableViewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,9 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 from collections import OrderedDict
+from functools import reduce
 
 import wx
 from matplotlib.backends.backend_wxagg import _convert_agg_to_wx_bitmap
@@ -375,7 +377,7 @@
         _width, height = self.GetSize()
 
         # Mouse is in the first half of Viewer
-        if y < height / 2:
+        if y < height // 2:
             # If Viewer is the upper one, draw drop before highlight
             if self.ParentWindow.IsViewerFirst(self):
                 self.SetHighlight(HIGHLIGHT_BEFORE)
--- a/controls/DiscoveryPanel.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/DiscoveryPanel.py	Fri Nov 23 12:13:24 2018 +0100
@@ -26,10 +26,12 @@
 
 from __future__ import absolute_import
 import socket
+from six.moves import xrange
 import wx
 import wx.lib.mixins.listctrl as listmix
 from zeroconf import ServiceBrowser, Zeroconf
 
+
 service_type = '_PYRO._tcp.local.'
 
 
--- a/controls/EnhancedStatusBar.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/EnhancedStatusBar.py	Fri Nov 23 12:13:24 2018 +0100
@@ -56,6 +56,7 @@
 """
 
 from __future__ import absolute_import
+from __future__ import division
 import wx
 
 # Horizontal Alignment Constants
@@ -145,7 +146,7 @@
                     widget.SetPosition((xpos, rect.y-1))
                 elif verticalalignment == ESB_ALIGN_CENTER_VERTICAL:
                     if widgetsize[1] < rect.height - 1:
-                        diffs = (rect.height - widgetsize[1])/2
+                        diffs = (rect.height - widgetsize[1]) // 2
                         widget.SetPosition((xpos, rect.y+diffs))
                     else:
                         widget.SetSize((widgetsize[0], rect.height-2))
@@ -163,7 +164,7 @@
                     widget.SetPosition((xpos, rect.y-1))
                 elif verticalalignment == ESB_ALIGN_CENTER_VERTICAL:
                     if widgetsize[1] < rect.height - 1:
-                        diffs = (rect.height - widgetsize[1])/2
+                        diffs = (rect.height - widgetsize[1]) // 2
                         widget.SetPosition((xpos, rect.y+diffs))
                     else:
                         widget.SetSize((widgetsize[0], rect.height-2))
@@ -175,13 +176,13 @@
 
             elif horizontalalignment == ESB_ALIGN_CENTER_HORIZONTAL:
 
-                xpos = rect.x + (rect.width - widgetsize[0])/2 - 1
+                xpos = rect.x + (rect.width - widgetsize[0]) // 2 - 1
                 if verticalalignment == ESB_EXACT_FIT:
                     widget.SetSize((widgetsize[0], rect.height))
                     widget.SetPosition((xpos, rect.y))
                 elif verticalalignment == ESB_ALIGN_CENTER_VERTICAL:
                     if widgetsize[1] < rect.height - 1:
-                        diffs = (rect.height - widgetsize[1])/2
+                        diffs = (rect.height - widgetsize[1]) // 2
                         widget.SetPosition((xpos, rect.y+diffs))
                     else:
                         widget.SetSize((widgetsize[0], rect.height-1))
@@ -221,19 +222,20 @@
             self._curPos += 1
 
         if self.GetFieldsCount() <= pos:
-            raise "\nERROR: EnhancedStatusBar has a max of %d items, you tried to set item #%d" % (self.GetFieldsCount(), pos)
+            raise ValueError("\nERROR: EnhancedStatusBar has a max of %d items, you tried to set item #%d" %
+                             (self.GetFieldsCount(), pos))
 
         if horizontalalignment not in [ESB_ALIGN_CENTER_HORIZONTAL, ESB_EXACT_FIT,
                                        ESB_ALIGN_LEFT, ESB_ALIGN_RIGHT]:
-            raise '\nERROR: Parameter "horizontalalignment" Should Be One Of '\
-                  '"ESB_ALIGN_CENTER_HORIZONTAL", "ESB_ALIGN_LEFT", "ESB_ALIGN_RIGHT"' \
-                  '"ESB_EXACT_FIT"'
+            raise ValueError('\nERROR: Parameter "horizontalalignment" Should Be One Of '
+                             '"ESB_ALIGN_CENTER_HORIZONTAL", "ESB_ALIGN_LEFT", "ESB_ALIGN_RIGHT"'
+                             '"ESB_EXACT_FIT"')
 
         if verticalalignment not in [ESB_ALIGN_CENTER_VERTICAL, ESB_EXACT_FIT,
                                      ESB_ALIGN_TOP, ESB_ALIGN_BOTTOM]:
-            raise '\nERROR: Parameter "verticalalignment" Should Be One Of '\
-                  '"ESB_ALIGN_CENTER_VERTICAL", "ESB_ALIGN_TOP", "ESB_ALIGN_BOTTOM"' \
-                  '"ESB_EXACT_FIT"'
+            raise ValueError('\nERROR: Parameter "verticalalignment" Should Be One Of '
+                             '"ESB_ALIGN_CENTER_VERTICAL", "ESB_ALIGN_TOP", "ESB_ALIGN_BOTTOM"'
+                             '"ESB_EXACT_FIT"')
 
         try:
             self.RemoveChild(self._items[pos].widget)
--- a/controls/FolderTree.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/FolderTree.py	Fri Nov 23 12:13:24 2018 +0100
@@ -27,6 +27,7 @@
 import os
 
 import wx
+from six.moves import xrange
 
 from util.BitmapLibrary import GetBitmap
 
--- a/controls/LibraryPanel.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/LibraryPanel.py	Fri Nov 23 12:13:24 2018 +0100
@@ -23,6 +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
 
 # -------------------------------------------------------------------------------
--- a/controls/LogViewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/LogViewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,12 +24,14 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 from datetime import datetime
 from time import time as gettime
 from weakref import proxy
 
 import numpy
 import wx
+from six.moves import xrange
 
 from controls.CustomToolTip import CustomToolTip, TOOLTIP_WAIT_PERIOD
 from editors.DebugViewer import DebugViewer, REFRESH_PERIOD
@@ -43,11 +45,11 @@
 def ArrowPoints(direction, width, height, xoffset, yoffset):
     if direction == wx.TOP:
         return [wx.Point(xoffset + 1, yoffset + height - 2),
-                wx.Point(xoffset + width / 2, yoffset + 1),
+                wx.Point(xoffset + width // 2, yoffset + 1),
                 wx.Point(xoffset + width - 1, yoffset + height - 2)]
     else:
         return [wx.Point(xoffset + 1, yoffset - height + 1),
-                wx.Point(xoffset + width / 2, yoffset - 2),
+                wx.Point(xoffset + width // 2, yoffset - 2),
                 wx.Point(xoffset + width - 1, yoffset - height + 1)]
 
 
@@ -124,7 +126,7 @@
             thumb_size = range_rect.height * THUMB_SIZE_RATIO
             thumb_range = range_rect.height - thumb_size
             self.RefreshThumbPosition(
-                max(-1., min((posy - self.ThumbScrollingStartPos.y) * 2. / thumb_range, 1.)))
+                max(-1., min((posy - self.ThumbScrollingStartPos.y) * 2. // thumb_range, 1.)))
         event.Skip()
 
     def OnResize(self, event):
@@ -146,11 +148,11 @@
         gc.SetPen(wx.Pen(wx.NamedColour("GREY"), 3))
         gc.SetBrush(wx.GREY_BRUSH)
 
-        gc.DrawLines(ArrowPoints(wx.TOP, width * 0.75, width * 0.5, 2, (width + height) / 4 - 3))
-        gc.DrawLines(ArrowPoints(wx.TOP, width * 0.75, width * 0.5, 2, (width + height) / 4 + 3))
-
-        gc.DrawLines(ArrowPoints(wx.BOTTOM, width * 0.75, width * 0.5, 2, (height * 3 - width) / 4 + 3))
-        gc.DrawLines(ArrowPoints(wx.BOTTOM, width * 0.75, width * 0.5, 2, (height * 3 - width) / 4 - 3))
+        gc.DrawLines(ArrowPoints(wx.TOP, width * 0.75, width * 0.5, 2, (width + height) // 4 - 3))
+        gc.DrawLines(ArrowPoints(wx.TOP, width * 0.75, width * 0.5, 2, (width + height) // 4 + 3))
+
+        gc.DrawLines(ArrowPoints(wx.BOTTOM, width * 0.75, width * 0.5, 2, (height * 3 - width) // 4 + 3))
+        gc.DrawLines(ArrowPoints(wx.BOTTOM, width * 0.75, width * 0.5, 2, (height * 3 - width) // 4 - 3))
 
         thumb_rect = self.GetThumbRect()
         exclusion_rect = wx.Rect(thumb_rect.x, thumb_rect.y,
@@ -222,8 +224,8 @@
 
         w, h = dc.GetTextExtent(self.Label)
         dc.DrawText(self.Label,
-                    self.Position.x + (self.Size.width - w) / 2,
-                    self.Position.y + (self.Size.height - h) / 2)
+                    self.Position.x + (self.Size.width - w) // 2,
+                    self.Position.y + (self.Size.height - h) // 2)
 
 
 DATE_INFO_SIZE = 10
@@ -259,19 +261,19 @@
         if draw_date:
             datetime_text = self.Date.strftime("%d/%m/%y %H:%M")
             dw, dh = dc.GetTextExtent(datetime_text)
-            dc.DrawText(datetime_text, (width - dw) / 2, offset + (DATE_INFO_SIZE - dh) / 2)
+            dc.DrawText(datetime_text, (width - dw) // 2, offset + (DATE_INFO_SIZE - dh) // 2)
             offset += DATE_INFO_SIZE
 
         seconds_text = "%12.9f" % self.Seconds
         sw, sh = dc.GetTextExtent(seconds_text)
-        dc.DrawText(seconds_text, 5, offset + (MESSAGE_INFO_SIZE - sh) / 2)
+        dc.DrawText(seconds_text, 5, offset + (MESSAGE_INFO_SIZE - sh) // 2)
 
         bw, bh = self.LevelBitmap.GetWidth(), self.LevelBitmap.GetHeight()
-        dc.DrawBitmap(self.LevelBitmap, 10 + sw, offset + (MESSAGE_INFO_SIZE - bh) / 2)
+        dc.DrawBitmap(self.LevelBitmap, 10 + sw, offset + (MESSAGE_INFO_SIZE - bh) // 2)
 
         text = self.Message.replace("\n", " ")
         _mw, mh = dc.GetTextExtent(text)
-        dc.DrawText(text, 15 + sw + bw, offset + (MESSAGE_INFO_SIZE - mh) / 2)
+        dc.DrawText(text, 15 + sw + bw, offset + (MESSAGE_INFO_SIZE - mh) // 2)
 
     def GetHeight(self, draw_date):
         if draw_date:
@@ -611,7 +613,7 @@
     def ScrollMessagePanelByPage(self, page):
         if self.CurrentMessage is not None:
             _width, height = self.MessagePanel.GetClientSize()
-            message_per_page = max(1, (height - DATE_INFO_SIZE) / MESSAGE_INFO_SIZE - 1)
+            message_per_page = max(1, (height - DATE_INFO_SIZE) // MESSAGE_INFO_SIZE - 1)
             self.ScrollMessagePanel(page * message_per_page)
 
     def ScrollMessagePanelByTimestamp(self, seconds):
@@ -756,7 +758,7 @@
         event.Skip()
 
     def OnMessagePanelMouseWheel(self, event):
-        self.ScrollMessagePanel(event.GetWheelRotation() / event.GetWheelDelta())
+        self.ScrollMessagePanel(event.GetWheelRotation() // event.GetWheelDelta())
         event.Skip()
 
     def OnMessagePanelEraseBackground(self, event):
--- a/controls/PouInstanceVariablesPanel.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/PouInstanceVariablesPanel.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,6 +24,7 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 from collections import namedtuple
 
 import wx
@@ -76,7 +77,7 @@
             bbox_width = (r_image_w + 4) * len(rightimages) + 4
             bbox_height = r_image_h + 8
             bbox_x = w - bbox_width
-            bbox_y = item.GetY() + ((total_h > r_image_h) and [(total_h-r_image_h)/2] or [0])[0]
+            bbox_y = item.GetY() + ((total_h > r_image_h) and [(total_h-r_image_h)//2] or [0])[0]
 
             return wx.Rect(bbox_x, bbox_y, bbox_width, bbox_height)
 
@@ -369,8 +370,8 @@
         self.InstanceChoice.SetFocusFromKbd()
         size = self.InstanceChoice.GetSize()
         event = wx.MouseEvent(wx.EVT_LEFT_DOWN._getEvtType())
-        event.x = size.width / 2
-        event.y = size.height / 2
+        event.x = size.width // 2
+        event.y = size.height // 2
         event.SetEventObject(self.InstanceChoice)
         # event = wx.KeyEvent(wx.EVT_KEY_DOWN._getEvtType())
         # event.m_keyCode = wx.WXK_SPACE
--- a/controls/SearchResultPanel.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/SearchResultPanel.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,7 @@
 
 
 from __future__ import absolute_import
-from types import TupleType
+from functools import reduce
 
 import wx
 import wx.lib.buttons
@@ -324,7 +324,7 @@
 
     def ShowSearchResults(self, item):
         data = self.SearchResultsTree.GetPyData(item)
-        if isinstance(data, TupleType):
+        if isinstance(data, tuple):
             search_results = [data]
         else:
             search_results = self.SearchResults.get(data, [])
--- a/controls/TextCtrlAutoComplete.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/TextCtrlAutoComplete.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,7 @@
 
 
 from __future__ import absolute_import
-import cPickle
+from six.moves import cPickle
 import wx
 
 MAX_ITEM_COUNT = 10
--- a/controls/VariablePanel.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/controls/VariablePanel.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,12 +24,15 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import re
-from types import TupleType, StringType, UnicodeType
+from builtins import str as text
 
 import wx
 import wx.grid
 import wx.lib.buttons
+from six import string_types
+from six.moves import xrange
 
 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS, DefaultType
 from plcopen.VariableInfoCollector import _VariableInfos
@@ -98,8 +101,8 @@
     "External": lambda x: {"Constant": "Constant"}.get(x, "")
 }
 
-LOCATION_MODEL = re.compile("((?:%[IQM](?:\*|(?:[XBWLD]?[0-9]+(?:\.[0-9]+)*)))?)$")
-LOCATION_MODEL_SET = re.compile("((?:%[IQM](?:[XBWLD]?[0-9]+(?:\.[0-9]+)*))?)$")
+LOCATION_MODEL = re.compile(r"((?:%[IQM](?:\*|(?:[XBWLD]?[0-9]+(?:\.[0-9]+)*)))?)$")
+LOCATION_MODEL_SET = re.compile(r"((?:%[IQM](?:[XBWLD]?[0-9]+(?:\.[0-9]+)*))?)$")
 
 
 # -------------------------------------------------------------------------------
@@ -137,10 +140,10 @@
             if colname == "Initial Value":
                 colname = "InitialValue"
             value = getattr(self.data[row], colname, "")
-            if colname == "Type" and isinstance(value, TupleType):
+            if colname == "Type" and isinstance(value, tuple):
                 if value[0] == "array":
                     return "ARRAY [%s] OF %s" % (",".join(map("..".join, value[2])), value[1])
-            if not isinstance(value, (StringType, UnicodeType)):
+            if not isinstance(value, string_types):
                 value = str(value)
             if colname in ["Class", "Option"]:
                 return _(value)
@@ -277,7 +280,7 @@
         except Exception:
             message = _("Invalid value \"%s\" for variable grid element") % data
             values = None
-        if not isinstance(values, TupleType):
+        if not isinstance(values, tuple):
             message = _("Invalid value \"%s\" for variable grid element") % data
             values = None
         if values is not None:
@@ -603,10 +606,10 @@
                 # increment location address
                 if row_content.Location != "" and LOCATION_MODEL_SET.match(row_content.Location):
                     old_location = row_content.Location
-                    model = re.compile("%[IQM][XBWLD]?(.*\.|)")
+                    model = re.compile(r"%[IQM][XBWLD]?(.*\.|)")
                     prefix = model.match(old_location).group(0)
                     addr = int(re.split(model, old_location)[-1]) + 1
-                    row_content.Location = prefix + unicode(addr)
+                    row_content.Location = prefix + text(addr)
 
             if not row_content.Class:
                 row_content.Class = self.DefaultTypes.get(self.Filter, self.Filter)
@@ -682,7 +685,7 @@
             self.VariablesGrid.SetColAttr(col, attr)
             self.VariablesGrid.SetColMinimalWidth(col, self.ColSettings["size"][col])
             if (panel_width > self.PanelWidthMin) and not self.ColSettings["fixed_size"][col]:
-                self.VariablesGrid.SetColSize(col, int((float(self.ColSettings["size"][col])/stretch_cols_sum)*stretch_cols_width))
+                self.VariablesGrid.SetColSize(col, int((self.ColSettings["size"][col]/stretch_cols_sum)*stretch_cols_width))
             else:
                 self.VariablesGrid.SetColSize(col, self.ColSettings["size"][col])
 
@@ -697,7 +700,7 @@
         return self.TagName
 
     def IsFunctionBlockType(self, name):
-        if isinstance(name, TupleType) or \
+        if isinstance(name, tuple) or \
            self.ElementType != "function" and self.BodyType in ["ST", "IL"]:
             return False
         else:
@@ -985,7 +988,7 @@
         event.Skip()
 
     def AddVariableHighlight(self, infos, highlight_type):
-        if isinstance(infos[0], TupleType):
+        if isinstance(infos[0], tuple):
             for i in xrange(*infos[0]):
                 self.Table.AddHighlight((i,) + infos[1:], highlight_type)
             cell_visible = infos[0][0]
@@ -997,7 +1000,7 @@
         self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
 
     def RemoveVariableHighlight(self, infos, highlight_type):
-        if isinstance(infos[0], TupleType):
+        if isinstance(infos[0], tuple):
             for i in xrange(*infos[0]):
                 self.Table.RemoveHighlight((i,) + infos[1:], highlight_type)
         else:
--- a/dialogs/ArrayTypeDialog.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/dialogs/ArrayTypeDialog.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,6 @@
 
 from __future__ import absolute_import
 import re
-from types import TupleType
 
 import wx
 
@@ -34,7 +33,7 @@
 #                                  Helpers
 # -------------------------------------------------------------------------------
 
-DIMENSION_MODEL = re.compile("([0-9]+)\.\.([0-9]+)$")
+DIMENSION_MODEL = re.compile(r"([0-9]+)\.\.([0-9]+)$")
 
 # -------------------------------------------------------------------------------
 #                             Array Type Dialog
@@ -83,7 +82,7 @@
         for datatype in datatypes:
             self.BaseType.Append(datatype)
 
-        if isinstance(infos, TupleType) and infos[0] == "array":
+        if isinstance(infos, tuple) and infos[0] == "array":
             self.BaseType.SetStringSelection(infos[1])
             self.Dimensions.SetStrings(map("..".join, infos[2]))
         elif infos in datatypes:
--- a/dialogs/BlockPreviewDialog.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/dialogs/BlockPreviewDialog.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,6 +25,7 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import wx
 
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
@@ -282,13 +283,13 @@
         k = 1.1 if (bbox.width * 1.1 > client_size.width or
                     bbox.height * 1.1 > client_size.height) \
             else 1.0
-        scale = (max(float(bbox.width) / client_size.width,
-                     float(bbox.height) / client_size.height) * k)
+        scale = (max(bbox.width / client_size.width,
+                     bbox.height / client_size.height) * k)
         dc.SetUserScale(1.0 / scale, 1.0 / scale)
 
         # Center graphic element in preview panel
-        x = int(client_size.width * scale - bbox.width) / 2 + posx - bbox.x
-        y = int(client_size.height * scale - bbox.height) / 2 + posy - bbox.y
+        x = int(client_size.width * scale - bbox.width) // 2 + posx - bbox.x
+        y = int(client_size.height * scale - bbox.height) // 2 + posy - bbox.y
         self.Element.SetPosition(x, y)
 
         # Draw graphic element
--- a/dialogs/DurationEditorDialog.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/dialogs/DurationEditorDialog.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,6 +25,7 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import re
 
 import wx
@@ -40,7 +41,7 @@
 HOUR = 60 * MINUTE
 DAY = 24 * HOUR
 
-IEC_TIME_MODEL = re.compile("(?:T|TIME)#(-)?(?:(%(float)s)D_?)?(?:(%(float)s)H_?)?(?:(%(float)s)M(?!S)_?)?(?:(%(float)s)S_?)?(?:(%(float)s)MS)?$" % {"float": "[0-9]+(?:\.[0-9]+)?"})
+IEC_TIME_MODEL = re.compile(r"(?:T|TIME)#(-)?(?:(%(float)s)D_?)?(?:(%(float)s)H_?)?(?:(%(float)s)M(?!S)_?)?(?:(%(float)s)S_?)?(?:(%(float)s)MS)?$" % {"float": r"[0-9]+(?:\.[0-9]+)?"})
 
 
 # -------------------------------------------------------------------------------
@@ -139,10 +140,10 @@
 
         not_null = False
         duration = "T#"
-        for value, format in [((int(milliseconds) / DAY),             "%dd"),
-                              ((int(milliseconds) % DAY) / HOUR,      "%dh"),
-                              ((int(milliseconds) % HOUR) / MINUTE,   "%dm"),
-                              ((int(milliseconds) % MINUTE) / SECOND, "%ds")]:
+        for value, format in [((int(milliseconds) // DAY),             "%dd"),
+                              ((int(milliseconds) % DAY) // HOUR,      "%dh"),
+                              ((int(milliseconds) % HOUR) // MINUTE,   "%dm"),
+                              ((int(milliseconds) % MINUTE) // SECOND, "%ds")]:
 
             if value > 0 or not_null:
                 duration += format % value
--- a/dialogs/ForceVariableDialog.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/dialogs/ForceVariableDialog.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,6 +25,7 @@
 from __future__ import absolute_import
 import re
 import datetime
+from builtins import str as text
 
 import wx
 
@@ -69,10 +70,10 @@
 HOUR = 60 * MINUTE
 DAY = 24 * HOUR
 
-IEC_TIME_MODEL = re.compile("(?:(?:T|TIME)#)?(-)?(?:(%(float)s)D_?)?(?:(%(float)s)H_?)?(?:(%(float)s)M(?!S)_?)?(?:(%(float)s)S_?)?(?:(%(float)s)MS)?$" % {"float": "[0-9]+(?:\.[0-9]+)?"})
-IEC_DATE_MODEL = re.compile("(?:(?:D|DATE)#)?([0-9]{4})-([0-9]{2})-([0-9]{2})$")
-IEC_DATETIME_MODEL = re.compile("(?:(?:DT|DATE_AND_TIME)#)?([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$")
-IEC_TIMEOFDAY_MODEL = re.compile("(?:(?:TOD|TIME_OF_DAY)#)?([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$")
+IEC_TIME_MODEL = re.compile(r"(?:(?:T|TIME)#)?(-)?(?:(%(float)s)D_?)?(?:(%(float)s)H_?)?(?:(%(float)s)M(?!S)_?)?(?:(%(float)s)S_?)?(?:(%(float)s)MS)?$" % {"float": r"[0-9]+(?:\.[0-9]+)?"})
+IEC_DATE_MODEL = re.compile(r"(?:(?:D|DATE)#)?([0-9]{4})-([0-9]{2})-([0-9]{2})$")
+IEC_DATETIME_MODEL = re.compile(r"(?:(?:DT|DATE_AND_TIME)#)?([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$")
+IEC_TIMEOFDAY_MODEL = re.compile(r"(?:(?:TOD|TIME_OF_DAY)#)?([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$")
 
 
 def gettime(v):
@@ -200,7 +201,7 @@
 
     def ToggleBoolValue(self, event):
         value = self.ToggleButton.GetValue()
-        self.ValueTextCtrl.SetValue(unicode(value))
+        self.ValueTextCtrl.SetValue(text(value))
 
     def OnOK(self, event):
         message = None
--- a/docutil/docpdf.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/docutil/docpdf.py	Fri Nov 23 12:13:24 2018 +0100
@@ -34,16 +34,16 @@
 
 def get_acroversion():
     " Return version of Adobe Acrobat executable or None"
-    import _winreg
-    adobesoft = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r'Software\Adobe')
-    for index in range(_winreg.QueryInfoKey(adobesoft)[0]):
-        key = _winreg.EnumKey(adobesoft, index)
+    from six.moves import winreg
+    adobesoft = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'Software\Adobe')
+    for index in range(winreg.QueryInfoKey(adobesoft)[0]):
+        key = winreg.EnumKey(adobesoft, index)
         if "acrobat" in key.lower():
-            acrokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'Software\\Adobe\\%s' % key)
-            for index in range(_winreg.QueryInfoKey(acrokey)[0]):
-                numver = _winreg.EnumKey(acrokey, index)
+            acrokey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'Software\\Adobe\\%s' % key)
+            for index in range(winreg.QueryInfoKey(acrokey)[0]):
+                numver = winreg.EnumKey(acrokey, index)
                 try:
-                    res = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE, 'Software\\Adobe\\%s\\%s\\InstallPath' % (key, numver))
+                    res = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE, 'Software\\Adobe\\%s\\%s\\InstallPath' % (key, numver))
                     return res
                 except Exception:
                     pass
--- a/docutil/docsvg.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/docutil/docsvg.py	Fri Nov 23 12:13:24 2018 +0100
@@ -31,13 +31,13 @@
 
 def get_inkscape_path():
     """ Return the Inkscape path """
-    import _winreg
+    from six.moves import winreg
     try:
-        svgexepath = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE,
-                                        'Software\\Classes\\svgfile\\shell\\Inkscape\\command')
+        svgexepath = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE,
+                                       'Software\\Classes\\svgfile\\shell\\Inkscape\\command')
     except OSError:
-        svgexepath = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE,
-                                        'Software\\Classes\\inkscape.svg\\shell\\open\\command')
+        svgexepath = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE,
+                                       'Software\\Classes\\inkscape.svg\\shell\\open\\command')
     svgexepath = svgexepath.replace('"%1"', '')
     return svgexepath.replace('"', '')
 
--- a/editors/CodeFileEditor.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/CodeFileEditor.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,12 +24,16 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import re
+from builtins import str as text
 
 import wx
 import wx.grid
 import wx.stc as stc
 import wx.lib.buttons
+from six.moves import xrange
+
 
 from plcopen.plcopen import TestTextElement
 from plcopen.structures import TestIdentifier, IEC_KEYWORDS, DefaultType
@@ -138,9 +142,9 @@
             section_comment = " %s section " % (section)
             len_headers = EDGE_COLUMN - len(section_comment)
             section_comment = \
-                self.COMMENT_HEADER * (len_headers / 2) + \
+                self.COMMENT_HEADER * (len_headers // 2) + \
                 section_comment + \
-                self.COMMENT_HEADER * (len_headers - len_headers / 2)
+                self.COMMENT_HEADER * (len_headers - len_headers // 2)
 
             self.SectionsComments[section] = {
                 "comment": section_comment,
@@ -629,7 +633,7 @@
             if col == 0:
                 return row + 1
             else:
-                return unicode(self.data[row].get(self.GetColLabelValue(col, False), ""))
+                return text(self.data[row].get(self.GetColLabelValue(col, False), ""))
 
     def _updateColAttrs(self, grid):
         """
--- a/editors/ConfTreeNodeEditor.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/ConfTreeNodeEditor.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,7 +25,7 @@
 
 
 from __future__ import absolute_import
-import types
+from __future__ import division
 
 import wx
 
@@ -100,11 +100,11 @@
         if not self.up:
             dw = dy = self.labelDelta
 
-        pos_x = (width-bw)/2+dw      # adjust for bitmap and text to centre
-        pos_y = (height-bh-th)/2+dy
+        pos_x = (width - bw) // 2 + dw      # adjust for bitmap and text to centre
+        pos_y = (height - bh - th) // 2 + dy
         if bmp is not None:
             dc.DrawBitmap(bmp, pos_x, pos_y, hasMask)  # draw bitmap if available
-            pos_x = (width-tw)/2+dw      # adjust for bitmap and text to centre
+            pos_x = (width-tw)//2+dw      # adjust for bitmap and text to centre
             pos_y += bh + 2
 
         dc.DrawText(label, pos_x, pos_y)      # draw the text
@@ -305,8 +305,8 @@
         self.Thaw()
 
     def GenerateMethodButtonSizer(self):
-        normal_bt_font = wx.Font(faces["size"] / 3,    wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName=faces["helv"])
-        mouseover_bt_font = wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName=faces["helv"], underline=True)
+        normal_bt_font = wx.Font(faces["size"] // 3,    wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName=faces["helv"])
+        mouseover_bt_font = wx.Font(faces["size"] // 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName=faces["helv"], underline=True)
 
         msizer = wx.BoxSizer(wx.HORIZONTAL)
 
@@ -402,8 +402,8 @@
                 boxsizer.AddWindow(statictext, border=5,
                                    flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT)
 
-                if isinstance(element_infos["type"], types.ListType):
-                    if isinstance(element_infos["value"], types.TupleType):
+                if isinstance(element_infos["type"], list):
+                    if isinstance(element_infos["value"], tuple):
                         browse_boxsizer = wx.BoxSizer(wx.HORIZONTAL)
                         boxsizer.AddSizer(browse_boxsizer)
 
@@ -429,7 +429,7 @@
 
                         if element_infos["use"] == "optional":
                             combobox.Append("")
-                        if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType):
+                        if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], tuple):
                             for choice, _xsdclass in element_infos["type"]:
                                 combobox.Append(choice)
                             name = element_infos["name"]
@@ -452,7 +452,7 @@
                             combobox.SetStringSelection(element_infos["value"])
                         combobox.Bind(wx.EVT_COMBOBOX, callback, combobox)
 
-                elif isinstance(element_infos["type"], types.DictType):
+                elif isinstance(element_infos["type"], dict):
                     scmin = -(2**31)
                     scmax = 2**31-1
                     if "min" in element_infos["type"]:
@@ -615,11 +615,12 @@
         xstart, ystart = self.ParamsEditor.GetViewStart()
         window_size = self.ParamsEditor.GetClientSize()
         maxx, maxy = self.ParamsEditorSizer.GetMinSize()
-        posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
-        posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
+        posx = max(0, min(xstart, (maxx - window_size[0]) // SCROLLBAR_UNIT))
+        posy = max(0, min(ystart, (maxy - window_size[1]) // SCROLLBAR_UNIT))
         self.ParamsEditor.Scroll(posx, posy)
         self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
-                                        maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT,
+                                        maxx // SCROLLBAR_UNIT,
+                                        maxy // SCROLLBAR_UNIT,
                                         posx, posy)
 
     def OnParamsEditorResize(self, event):
--- a/editors/DataTypeEditor.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/DataTypeEditor.py	Fri Nov 23 12:13:24 2018 +0100
@@ -26,7 +26,7 @@
 
 from __future__ import absolute_import
 import re
-from types import TupleType
+from six.moves import xrange
 
 import wx
 import wx.grid
@@ -43,7 +43,7 @@
 #                                    Helpers
 # -------------------------------------------------------------------------------
 
-DIMENSION_MODEL = re.compile("([0-9]+)\.\.([0-9]+)$")
+DIMENSION_MODEL = re.compile(r"([0-9]+)\.\.([0-9]+)$")
 
 
 def AppendMenu(parent, help, id, kind, text):
@@ -82,7 +82,7 @@
             colname = self.GetColLabelValue(col, False)
             value = self.data[row].get(colname, "")
 
-            if colname == "Type" and isinstance(value, TupleType):
+            if colname == "Type" and isinstance(value, tuple):
                 if value[0] == "array":
                     return "ARRAY [%s] OF %s" % (",".join(map("..".join, value[2])), value[1])
             return value
--- a/editors/LDViewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/LDViewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,9 +24,11 @@
 
 
 from __future__ import absolute_import
-from types import *
+from __future__ import division
+from future.builtins import round
 
 import wx
+from six.moves import xrange
 
 from editors.Viewer import *
 
@@ -159,7 +161,7 @@
                 return
         if not parts:
             parts = 1
-        element_tree[element]["weight"] = max(1, weight / parts)
+        element_tree[element]["weight"] = max(1, weight // parts)
 
 
 # -------------------------------------------------------------------------------
@@ -456,10 +458,10 @@
                 contact = LD_Contact(self, CONTACT_NORMAL, var_name, id)
                 width, height = contact.GetMinSize()
                 if scaling is not None:
-                    x = round(float(x) / float(scaling[0])) * scaling[0]
-                    y = round(float(y) / float(scaling[1])) * scaling[1]
-                    width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
-                    height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
+                    x = round(x / scaling[0]) * scaling[0]
+                    y = round(y / scaling[1]) * scaling[1]
+                    width = round(width / scaling[0] + 0.5) * scaling[0]
+                    height = round(height / scaling[1] + 0.5) * scaling[1]
                 contact.SetPosition(x, y)
                 contact.SetSize(width, height)
                 self.AddBlock(contact)
@@ -469,10 +471,10 @@
                 coil = LD_Coil(self, COIL_NORMAL, var_name, id)
                 width, height = coil.GetMinSize()
                 if scaling is not None:
-                    x = round(float(x) / float(scaling[0])) * scaling[0]
-                    y = round(float(y) / float(scaling[1])) * scaling[1]
-                    width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
-                    height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
+                    x = round(x / scaling[0]) * scaling[0]
+                    y = round(y / scaling[1]) * scaling[1]
+                    width = round(width / scaling[0] + 0.5) * scaling[0]
+                    height = round(height / scaling[1] + 0.5) * scaling[1]
                 coil.SetPosition(x, y)
                 coil.SetSize(width, height)
                 self.AddBlock(coil)
@@ -536,7 +538,7 @@
             # Create Coil
             id = self.GetNewId()
             coil = LD_Coil(self, values["type"], values["name"], id)
-            coil.SetPosition(startx, starty + (LD_LINE_SIZE - LD_ELEMENT_SIZE[1]) / 2)
+            coil.SetPosition(startx, starty + (LD_LINE_SIZE - LD_ELEMENT_SIZE[1]) // 2)
             coil_connectors = coil.GetConnectors()
             self.AddBlock(coil)
             rung.SelectElement(coil)
@@ -605,7 +607,7 @@
                 points = wires[0].GetSelectedSegmentPoints()
                 id = self.GetNewId()
                 contact = LD_Contact(self, values["type"], values["name"], id)
-                contact.SetPosition(0, points[0].y - (LD_ELEMENT_SIZE[1] + 1) / 2)
+                contact.SetPosition(0, points[0].y - (LD_ELEMENT_SIZE[1] + 1) // 2)
                 self.AddBlock(contact)
                 self.Controler.AddEditedElementContact(self.TagName, id)
                 rungindex = self.FindRung(wires[0])
--- a/editors/ResourceEditor.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/ResourceEditor.py	Fri Nov 23 12:13:24 2018 +0100
@@ -27,6 +27,7 @@
 import wx
 import wx.lib.buttons
 import wx.grid
+from six.moves import xrange
 
 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT
 from controls import CustomGrid, CustomTable, DurationCellEditor
--- a/editors/SFCViewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/SFCViewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,7 @@
 
 
 from __future__ import absolute_import
-from types import *
+from __future__ import division
 
 import wx
 
@@ -534,7 +534,7 @@
                     pos = connectors["action"].GetPosition(False)
                     id = self.GetNewId()
                     actionblock = SFC_ActionBlock(self, [], id)
-                    actionblock.SetPosition(pos.x + SFC_WIRE_MIN_SIZE, pos.y - SFC_STEP_DEFAULT_SIZE[1] / 2)
+                    actionblock.SetPosition(pos.x + SFC_WIRE_MIN_SIZE, pos.y - SFC_STEP_DEFAULT_SIZE[1] // 2)
                     actionblock_connector = actionblock.GetConnector()
                     wire = self.ConnectConnectors(actionblock_connector, connectors["action"])
                     wire.SetPoints([wx.Point(pos.x + SFC_WIRE_MIN_SIZE, pos.y), wx.Point(pos.x, pos.y)])
--- a/editors/TextViewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/TextViewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,11 +24,13 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import re
-from types import *
+from functools import reduce
 
 import wx
 import wx.stc
+from six.moves import xrange
 
 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
 from plcopen.structures import ST_BLOCK_START_KEYWORDS, IEC_BLOCK_START_KEYWORDS, LOCATIONDATATYPES
@@ -892,7 +894,7 @@
                 if self.TextSyntax in ["ST", "ALL"]:
                     indent = self.Editor.GetLineIndentation(line)
                     if LineStartswith(lineText.strip(), self.BlockStartKeywords):
-                        indent = (indent / 2 + 1) * 2
+                        indent = (indent // 2 + 1) * 2
                     self.Editor.AddText("\n" + " " * indent)
                     key_handled = True
             elif key == wx.WXK_BACK:
@@ -901,7 +903,7 @@
                         indent = self.Editor.GetColumn(self.Editor.GetCurrentPos())
                         if lineText.strip() == "" and len(lineText) > 0 and indent > 0:
                             self.Editor.DelLineLeft()
-                            self.Editor.AddText(" " * ((max(0, indent - 1) / 2) * 2))
+                            self.Editor.AddText(" " * ((max(0, indent - 1) // 2) * 2))
                             key_handled = True
             if not key_handled:
                 event.Skip()
--- a/editors/Viewer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/editors/Viewer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,12 +24,14 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import math
 from time import time as gettime
-from types import TupleType
 from threading import Lock
+from future.builtins import round
 
 import wx
+from six.moves import xrange
 
 from plcopen.structures import *
 from plcopen.types_enums import ComputePouName
@@ -275,7 +277,7 @@
         except Exception:
             message = _("Invalid value \"%s\" for viewer block") % data
             values = None
-        if not isinstance(values, TupleType):
+        if not isinstance(values, tuple):
             message = _("Invalid value \"%s\" for viewer block") % data
             values = None
         if values is not None:
@@ -307,10 +309,10 @@
                         block = FBD_Block(self.ParentWindow, values[0], blockname, id, inputs=blockinputs)
                         width, height = block.GetMinSize()
                         if scaling is not None:
-                            x = round(float(x) / float(scaling[0])) * scaling[0]
-                            y = round(float(y) / float(scaling[1])) * scaling[1]
-                            width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
-                            height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
+                            x = round(x / scaling[0]) * scaling[0]
+                            y = round(y / scaling[1]) * scaling[1]
+                            width = round(width / scaling[0] + 0.5) * scaling[0]
+                            height = round(height / scaling[1] + 0.5) * scaling[1]
                         block.SetPosition(x, y)
                         block.SetSize(width, height)
                         self.ParentWindow.AddBlock(block)
@@ -859,7 +861,7 @@
                 self.Editor.Freeze()
                 if mouse_event is None:
                     client_size = self.Editor.GetClientSize()
-                    mouse_pos = wx.Point(client_size[0] / 2, client_size[1] / 2)
+                    mouse_pos = wx.Point(client_size[0] // 2, client_size[1] // 2)
                     mouse_event = wx.MouseEvent(wx.EVT_MOUSEWHEEL.typeId)
                     mouse_event.x = mouse_pos.x
                     mouse_event.y = mouse_pos.y
@@ -1338,7 +1340,8 @@
         maxy = int(maxy * self.ViewScale[1])
         self.Editor.SetScrollbars(
             SCROLLBAR_UNIT, SCROLLBAR_UNIT,
-            round(maxx / SCROLLBAR_UNIT) + width_incr, round(maxy / SCROLLBAR_UNIT) + height_incr,
+            round(maxx / SCROLLBAR_UNIT) + width_incr,
+            round(maxy / SCROLLBAR_UNIT) + height_incr,
             xstart, ystart, True)
 
     def EnsureVisible(self, block):
@@ -1355,13 +1358,13 @@
 
         xpos, ypos = xstart, ystart
         if block_minx < screen_minx and block_maxx < screen_maxx:
-            xpos -= (screen_minx - block_minx) / SCROLLBAR_UNIT + 1
+            xpos -= (screen_minx - block_minx) // SCROLLBAR_UNIT + 1
         elif block_maxx > screen_maxx and block_minx > screen_minx:
-            xpos += (block_maxx - screen_maxx) / SCROLLBAR_UNIT + 1
+            xpos += (block_maxx - screen_maxx) // SCROLLBAR_UNIT + 1
         if block_miny < screen_miny and block_maxy < screen_maxy:
-            ypos -= (screen_miny - block_miny) / SCROLLBAR_UNIT + 1
+            ypos -= (screen_miny - block_miny) // SCROLLBAR_UNIT + 1
         elif block_maxy > screen_maxy and block_miny > screen_miny:
-            ypos += (block_maxy - screen_maxy) / SCROLLBAR_UNIT + 1
+            ypos += (block_maxy - screen_maxy) // SCROLLBAR_UNIT + 1
         self.Scroll(xpos, ypos)
 
     def SelectInGroup(self, element):
@@ -2316,8 +2319,8 @@
                 new_pos = event.GetPosition()
                 xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
                 ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
-                scrollx = max(0, self.StartScreenPos[0] - (new_pos[0] - self.StartMousePos[0]) / SCROLLBAR_UNIT)
-                scrolly = max(0, self.StartScreenPos[1] - (new_pos[1] - self.StartMousePos[1]) / SCROLLBAR_UNIT)
+                scrollx = max(0, self.StartScreenPos[0] - (new_pos[0] - self.StartMousePos[0]) // SCROLLBAR_UNIT)
+                scrolly = max(0, self.StartScreenPos[1] - (new_pos[1] - self.StartMousePos[1]) // SCROLLBAR_UNIT)
                 if scrollx > xmax or scrolly > ymax:
                     self.RefreshScrollBars(max(0, scrollx - xmax), max(0, scrolly - ymax))
                     self.Scroll(scrollx, scrolly)
@@ -2545,10 +2548,10 @@
         variable = FBD_Variable(self, var_class, var_name, var_type, id)
         width, height = variable.GetMinSize()
         if scaling is not None:
-            x = round(float(x) / float(scaling[0])) * scaling[0]
-            y = round(float(y) / float(scaling[1])) * scaling[1]
-            width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
-            height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
+            x = round(x / scaling[0]) * scaling[0]
+            y = round(y / scaling[1]) * scaling[1]
+            width = round(width / scaling[0] + 0.5) * scaling[0]
+            height = round(height / scaling[1] + 0.5) * scaling[1]
         variable.SetPosition(x, y)
         variable.SetSize(width, height)
         self.AddBlock(variable)
@@ -2565,8 +2568,8 @@
 
     def GetScaledSize(self, width, height):
         if self.Scaling is not None:
-            width = round(float(width) / float(self.Scaling[0]) + 0.4) * self.Scaling[0]
-            height = round(float(height) / float(self.Scaling[1]) + 0.4) * self.Scaling[1]
+            width = round(width / self.Scaling[0] + 0.4) * self.Scaling[0]
+            height = round(height / self.Scaling[1] + 0.4) * self.Scaling[1]
         return width, height
 
     def AddNewElement(self, element, bbox, wire=None, connector=None):
@@ -3451,7 +3454,7 @@
                 middle = True
                 new_pos = [bbx.x, bbx.y]
             result = self.Controler.PasteEditedElementInstances(self.TagName, element, new_pos, middle, self.Debug)
-            if not isinstance(result, (StringType, UnicodeType)):
+            if not isinstance(result, string_types):
                 self.RefreshBuffer()
                 self.RefreshView(selection=result)
                 self.RefreshVariablePanel()
--- a/etherlab/CommonEtherCATFunction.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/etherlab/CommonEtherCATFunction.py	Fri Nov 23 12:13:24 2018 +0100
@@ -9,8 +9,12 @@
 # See COPYING file for copyrights details.
 
 from __future__ import absolute_import
+from __future__ import division
+from builtins import str as text
+import codecs
 import wx
 
+
 mailbox_protocols = ["AoE", "EoE", "CoE", "FoE", "SoE", "VoE"]
 
 
@@ -182,7 +186,7 @@
         @param controler: _EthercatSlaveCTN class in EthercatSlave.py
         """
         self.Controler = controler
-
+        self.HexDecode = codecs.getdecoder("hex_codec")
         self.ClearSDODataSet()
 
     # -------------------------------------------------------------------------------
@@ -549,7 +553,7 @@
         if (value_len % 2) == 0:
             hex_len = value_len
         else:
-            hex_len = (value_len / 2) * 2 + 2
+            hex_len = (value_len // 2) * 2 + 2
 
         hex_data = ("{:0>"+str(hex_len)+"x}").format(decnum)
 
@@ -589,7 +593,7 @@
 
         # append zero-filled padding data up to EEPROM size
         for dummy in range(self.SmartViewInfosFromXML["eeprom_size"] - len(self.BinaryCode)):
-            self.BinaryCode = self.BinaryCode + 'ff'.decode('hex')
+            self.BinaryCode = self.BinaryCode + self.HexDecode('ff')[0]
 
         return self.BinaryCode
 
@@ -648,7 +652,7 @@
         eeprom_list = []
 
         if direction is 0 or 1:
-            for dummy in range(length/2):
+            for dummy in range(length//2):
                 if data == "":
                     eeprom_list.append("00")
                 else:
@@ -808,7 +812,7 @@
             for eeprom_element in device.getEeprom().getcontent():
                 if eeprom_element["name"] == "ByteSize":
                     eeprom_size = int(str(eeprom_element))
-                    data = "{:0>4x}".format(int(eeprom_element)/1024*8-1)
+                    data = "{:0>4x}".format(int(eeprom_element)//1024*8-1)
 
             if data == "":
                 eeprom.append("00")
@@ -857,7 +861,7 @@
 
             # convert binary code
             for index in range(eeprom_size):
-                eeprom_binary = eeprom_binary + eeprom[index].decode('hex')
+                eeprom_binary = eeprom_binary + self.HexDecode(eeprom[index])[0]
 
             return eeprom_binary
 
@@ -894,7 +898,7 @@
         vendor_spec_strings = []
         for element in device.getType().getcontent():
             data += element
-        if data != "" and isinstance(data, unicode):
+        if data != "" and isinstance(data, text):
             for vendor_spec_string in vendor_spec_strings:
                 if data == vendor_spec_string:
                     self.OrderIdx = vendor_spec_strings.index(data)+1
@@ -913,7 +917,7 @@
 
         #  element2-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<GroupType>
         data = device.getGroupType()
-        if data is not None and isinstance(data, unicode):
+        if data is not None and isinstance(data, text):
             for vendor_spec_string in vendor_spec_strings:
                 if data == vendor_spec_string:
                     self.GroupIdx = vendor_spec_strings.index(data)+1
@@ -937,7 +941,7 @@
                         for device_item in group_etc["devices"]:
                             if device == device_item[1]:
                                 data = group_type
-                if data is not None and isinstance(data, unicode):
+                if data is not None and isinstance(data, text):
                     for vendor_spec_string in vendor_spec_strings:
                         if data == vendor_spec_string:
                             self.GroupIdx = vendor_spec_strings.index(data)+1
@@ -961,7 +965,7 @@
                     for device_item in group_etc["devices"]:
                         if device == device_item[1]:
                             data = group_etc["name"]
-        if data != "" and isinstance(data, unicode):
+        if data != "" and isinstance(data, text):
             for vendor_spec_string in vendor_spec_strings:
                 if data == vendor_spec_string:
                     groupnameflag = True
@@ -980,7 +984,7 @@
         for element in device.getName():
             if element.getLcId() == 1 or element.getLcId() == 1033:
                 data = element.getcontent()
-        if data != "" and isinstance(data, unicode):
+        if data != "" and isinstance(data, text):
             for vendor_spec_string in vendor_spec_strings:
                 if data == vendor_spec_string:
                     self.NameIdx = vendor_spec_strings.index(data)+1
@@ -1000,7 +1004,7 @@
         #  element5-1; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Image16x14>
         if device.getcontent() is not None:
             data = device.getcontent()
-            if data is not None and isinstance(data, unicode):
+            if data is not None and isinstance(data, text):
                 for vendor_spec_string in vendor_spec_strings:
                     if data == vendor_spec_string:
                         self.ImgIdx = vendor_spec_strings.index(data)+1
@@ -1024,7 +1028,7 @@
                         for device_item in group_etc["devices"]:
                             if device == device_item[1]:
                                 data = group_etc
-                if data is not None and isinstance(data, unicode):
+                if data is not None and isinstance(data, text):
                     for vendor_spec_string in vendor_spec_strings:
                         if data == vendor_spec_string:
                             self.ImgIdx = vendor_spec_strings.index(data)+1
@@ -1132,15 +1136,15 @@
         else:
             length += length % 4
             padflag = True
-        eeprom.append("{:0>4x}".format(length/4)[2:4])
-        eeprom.append("{:0>4x}".format(length/4)[0:2])
+        eeprom.append("{:0>4x}".format(length//4)[2:4])
+        eeprom.append("{:0>4x}".format(length//4)[0:2])
         #  total numbers of strings
         eeprom.append("{:0>2x}".format(count))
         for element in [vendor_specific_data,
                         dc_related_elements,
                         input_elements,
                         output_elements]:
-            for dummy in range(len(element)/2):
+            for dummy in range(len(element)//2):
                 if element == "":
                     eeprom.append("00")
                 else:
@@ -1285,11 +1289,11 @@
             #  category length
             if count % 2 == 1:
                 padflag = True
-                eeprom.append("{:0>4x}".format((count+1)/2)[2:4])
-                eeprom.append("{:0>4x}".format((count+1)/2)[0:2])
+                eeprom.append("{:0>4x}".format((count+1)//2)[2:4])
+                eeprom.append("{:0>4x}".format((count+1)//2)[0:2])
             else:
-                eeprom.append("{:0>4x}".format((count)/2)[2:4])
-                eeprom.append("{:0>4x}".format((count)/2)[0:2])
+                eeprom.append("{:0>4x}".format((count)//2)[2:4])
+                eeprom.append("{:0>4x}".format((count)//2)[0:2])
             for dummy in range(count):
                 if data == "":
                     eeprom.append("00")
@@ -1332,9 +1336,9 @@
             eeprom.append("29")
             eeprom.append("00")
             #  category length
-            eeprom.append("{:0>4x}".format(len(data)/4)[2:4])
-            eeprom.append("{:0>4x}".format(len(data)/4)[0:2])
-            for dummy in range(len(data)/2):
+            eeprom.append("{:0>4x}".format(len(data)//4)[2:4])
+            eeprom.append("{:0>4x}".format(len(data)//4)[0:2])
+            for dummy in range(len(data)//2):
                 if data == "":
                     eeprom.append("00")
                 else:
@@ -1440,10 +1444,10 @@
                 eeprom.append("00")
             eeprom.append("00")
             #  category length
-            eeprom.append("{:0>4x}".format(len(data)/4)[2:4])
-            eeprom.append("{:0>4x}".format(len(data)/4)[0:2])
+            eeprom.append("{:0>4x}".format(len(data)//4)[2:4])
+            eeprom.append("{:0>4x}".format(len(data)//4)[0:2])
             data = str(data.lower())
-            for dummy in range(len(data)/2):
+            for dummy in range(len(data)//2):
                 if data == "":
                     eeprom.append("00")
                 else:
@@ -1514,10 +1518,10 @@
             eeprom.append("3c")
             eeprom.append("00")
             #  category length
-            eeprom.append("{:0>4x}".format(len(data)/4)[2:4])
-            eeprom.append("{:0>4x}".format(len(data)/4)[0:2])
+            eeprom.append("{:0>4x}".format(len(data)//4)[2:4])
+            eeprom.append("{:0>4x}".format(len(data)//4)[0:2])
             data = str(data.lower())
-            for dummy in range(len(data)/2):
+            for dummy in range(len(data)//2):
                 if data == "":
                     eeprom.append("00")
                 else:
--- a/etherlab/ConfigEditor.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/etherlab/ConfigEditor.py	Fri Nov 23 12:13:24 2018 +0100
@@ -10,9 +10,9 @@
 # See COPYING file for copyrights details.
 
 from __future__ import absolute_import
+from __future__ import division
 import os
 import re
-from types import TupleType
 
 import wx
 import wx.grid
@@ -71,7 +71,7 @@
 
 ETHERCAT_INDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,4})$")
 ETHERCAT_SUBINDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,2})$")
-LOCATION_MODEL = re.compile("(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$")
+LOCATION_MODEL = re.compile(r"(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$")
 
 
 class NodeVariablesSizer(wx.FlexGridSizer):
@@ -324,12 +324,12 @@
         xstart, ystart = self.EtherCATManagementEditor.GetViewStart()
         window_size = self.EtherCATManagementEditor.GetClientSize()
         maxx, maxy = self.EtherCATManagementEditor.GetMinSize()
-        posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
-        posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
+        posx = max(0, min(xstart, (maxx - window_size[0]) // SCROLLBAR_UNIT))
+        posy = max(0, min(ystart, (maxy - window_size[1]) // SCROLLBAR_UNIT))
         self.EtherCATManagementEditor.Scroll(posx, posy)
         self.EtherCATManagementEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
-                                                    maxx / SCROLLBAR_UNIT,
-                                                    maxy / SCROLLBAR_UNIT,
+                                                    maxx // SCROLLBAR_UNIT,
+                                                    maxy // SCROLLBAR_UNIT,
                                                     posx, posy)
         event.Skip()
     # -------------------------------------------------------------------------------------------------------
@@ -417,7 +417,7 @@
         except Exception:
             message = _("Invalid value \"%s\" for process variable") % data
             values = None
-        if not isinstance(values, TupleType):
+        if not isinstance(values, tuple):
             message = _("Invalid value \"%s\" for process variable") % data
             values = None
         if values is not None and col != wx.NOT_FOUND and row != wx.NOT_FOUND and 2 <= col <= 3:
@@ -479,7 +479,7 @@
         except Exception:
             message = _("Invalid value \"%s\" for startup command") % data
             values = None
-        if not isinstance(values, TupleType):
+        if not isinstance(values, tuple):
             message = _("Invalid value \"%s\" for startup command") % data
             values = None
         if values is not None:
@@ -1056,12 +1056,12 @@
         xstart, ystart = self.EthercatMasterEditor.GetViewStart()
         window_size = self.EthercatMasterEditor.GetClientSize()
         maxx, maxy = self.EthercatMasterEditorSizer.GetMinSize()
-        posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
-        posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
+        posx = max(0, min(xstart, (maxx - window_size[0]) // SCROLLBAR_UNIT))
+        posy = max(0, min(ystart, (maxy - window_size[1]) // SCROLLBAR_UNIT))
         self.EthercatMasterEditor.Scroll(posx, posy)
         self.EthercatMasterEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
-                                                maxx / SCROLLBAR_UNIT,
-                                                maxy / SCROLLBAR_UNIT,
+                                                maxx // SCROLLBAR_UNIT,
+                                                maxy // SCROLLBAR_UNIT,
                                                 posx, posy)
         event.Skip()
 
@@ -1421,11 +1421,11 @@
         xstart, ystart = self.ModuleLibraryEditor.GetViewStart()
         window_size = self.ModuleLibraryEditor.GetClientSize()
         maxx, maxy = self.ModuleLibraryEditor.GetMinSize()
-        posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
-        posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
+        posx = max(0, min(xstart, (maxx - window_size[0]) // SCROLLBAR_UNIT))
+        posy = max(0, min(ystart, (maxy - window_size[1]) // SCROLLBAR_UNIT))
         self.ModuleLibraryEditor.Scroll(posx, posy)
         self.ModuleLibraryEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
-                                               maxx / SCROLLBAR_UNIT,
-                                               maxy / SCROLLBAR_UNIT,
+                                               maxx // SCROLLBAR_UNIT,
+                                               maxy // SCROLLBAR_UNIT,
                                                posx, posy)
         event.Skip()
--- a/etherlab/EtherCATManagementEditor.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/etherlab/EtherCATManagementEditor.py	Fri Nov 23 12:13:24 2018 +0100
@@ -8,6 +8,7 @@
 # See COPYING file for copyrights details.
 
 from __future__ import absolute_import
+from __future__ import division
 import os
 import string
 from xml.dom import minidom
@@ -422,7 +423,7 @@
 
                 self.Controler.CommonMethod.SaveSDOData[self.AllSDOData].append(self.Data)
 
-            if count >= len(self.SDOs.splitlines()) / 2:
+            if count >= len(self.SDOs.splitlines()) // 2:
                 (keep_going, _skip) = slaveSDO_progress.Update(count, "Please waiting a moment!!")
             else:
                 (keep_going, _skip) = slaveSDO_progress.Update(count)
@@ -1034,7 +1035,7 @@
 
         # Config Data: EEPROM Size, PDI Type, Device Emulation
         # EEPROM's data in address '0x003f' is Size of EEPROM in KBit-1
-        eeprom_size = str((int(self.GetWordAddressData(sii_dict.get('Size'), 10))+1)/8*1024)
+        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():
@@ -1363,10 +1364,10 @@
         for col in range(self.Col):
             if col == 16:
                 self.SetColLabelValue(16, "Text View")
-                self.SetColSize(16, (self.GetSize().x-120)*4/20)
+                self.SetColSize(16, (self.GetSize().x-120)*4//20)
             else:
                 self.SetColLabelValue(col, '%s' % col)
-                self.SetColSize(col, (self.GetSize().x-120)/20)
+                self.SetColSize(col, (self.GetSize().x-120)//20)
 
         # set data into table
         row = col = 0
--- a/etherlab/EthercatCFileGenerator.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/etherlab/EthercatCFileGenerator.py	Fri Nov 23 12:13:24 2018 +0100
@@ -10,6 +10,7 @@
 # See COPYING file for copyrights details.
 
 from __future__ import absolute_import
+from __future__ import division
 import os
 
 from etherlab.EthercatSlave import ExtractHexDecValue, DATATYPECONVERSION, ExtractName
@@ -254,7 +255,7 @@
                     subindex = initCmd["Subindex"]
                     entry = device_entries.get((index, subindex), None)
                     if entry is not None:
-                        data_size = entry["BitSize"] / 8
+                        data_size = entry["BitSize"] // 8
                         data_str = ("0x%%.%dx" % (data_size * 2)) % initCmd["Value"]
                         init_cmd_infos = {
                             "index": index,
@@ -413,7 +414,7 @@
                         elif pdo_type == "Outputs" and entry.getDataType() is not None and device_coe is not None:
                             data_type = entry.getDataType().getcontent()
                             entry_infos["dir"] = "Q"
-                            entry_infos["data_size"] = max(1, entry_infos["bitlen"] / 8)
+                            entry_infos["data_size"] = max(1, entry_infos["bitlen"] // 8)
                             entry_infos["data_type"] = DATATYPECONVERSION.get(data_type)
                             entry_infos["var_type"] = data_type
                             entry_infos["real_var"] = "slave%(slave)d_%(index).4x_%(subindex).2x_default" % entry_infos
--- a/etherlab/EthercatMaster.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/etherlab/EthercatMaster.py	Fri Nov 23 12:13:24 2018 +0100
@@ -12,6 +12,7 @@
 from __future__ import absolute_import
 import os
 from copy import deepcopy
+from functools import reduce
 from lxml import etree
 
 import wx
@@ -94,7 +95,7 @@
         ethelabfile.close()
 
         return ((["etherlab_ext"], [(Gen_etherlabfile_path, IECCFLAGS)], True), "",
-                ("runtime_etherlab.py", file(GetLocalPath("runtime_etherlab.py"))))
+                ("runtime_etherlab.py", open(GetLocalPath("runtime_etherlab.py"))))
 
 # --------------------------------------------------
 #                 Ethercat MASTER
@@ -250,7 +251,7 @@
                 if error is None:
                     config_is_saved = True
             except Exception as e:
-                error = e.message
+                error = str(e)
             config_xmlfile.close()
 
             if error is not None:
@@ -271,7 +272,7 @@
                 if error is None:
                     process_is_saved = True
             except Exception as e:
-                error = e.message
+                error = str(e)
             process_xmlfile.close()
 
             if error is not None:
--- a/etherlab/etherlab.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/etherlab/etherlab.py	Fri Nov 23 12:13:24 2018 +0100
@@ -13,8 +13,9 @@
 import os
 import shutil
 import csv
+from builtins import str as text
+
 from lxml import etree
-
 import wx
 
 from xmlclass import *
@@ -227,7 +228,7 @@
                         self.GetCTRoot().logger.write_warning(
                             XSDSchemaErrorMessage % (filepath + error))
                 except Exception as exc:
-                    self.modules_infos, error = None, unicode(exc)
+                    self.modules_infos, error = None, text(exc)
                 xmlfile.close()
 
                 if self.modules_infos is not None:
--- a/graphics/DebugDataConsumer.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/graphics/DebugDataConsumer.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,6 +24,7 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import datetime
 
 
@@ -76,10 +77,10 @@
     not_null = False
 
     for val, format in [
-            (int(microseconds) / DAY, "%dd"),                 # Days
-            ((int(microseconds) % DAY) / HOUR, "%dh"),        # Hours
-            ((int(microseconds) % HOUR) / MINUTE, "%dm"),     # Minutes
-            ((int(microseconds) % MINUTE) / SECOND, "%ds")]:  # Seconds
+            (int(microseconds) // DAY, "%dd"),                 # Days
+            ((int(microseconds) % DAY) // HOUR, "%dh"),        # Hours
+            ((int(microseconds) % HOUR) // MINUTE, "%dm"),     # Minutes
+            ((int(microseconds) % MINUTE) // SECOND, "%ds")]:  # Seconds
 
         # Add value to TIME literal if value is non-null or another non-null
         # value have already be found
@@ -128,9 +129,9 @@
     data = "TOD#"
 
     for val, format in [
-            (int(microseconds) / HOUR, "%2.2d:"),               # Hours
-            ((int(microseconds) % HOUR) / MINUTE, "%2.2d:"),    # Minutes
-            ((int(microseconds) % MINUTE) / SECOND, "%2.2d."),  # Seconds
+            (int(microseconds) // HOUR, "%2.2d:"),               # Hours
+            ((int(microseconds) % HOUR) // MINUTE, "%2.2d:"),    # Minutes
+            ((int(microseconds) % MINUTE) // SECOND, "%2.2d."),  # Seconds
             (microseconds % SECOND, "%6.6d")]:                  # Microseconds
 
         # Add value to TIME_OF_DAY literal
--- a/graphics/FBD_Objects.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/graphics/FBD_Objects.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,9 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import wx
+from six.moves import xrange
 
 from graphics.GraphicCommons import *
 from plcopen.structures import *
@@ -130,7 +132,7 @@
     def GetTextBoundingBox(self):
         # Calculate the size of the name outside the block
         text_width, text_height = self.NameSize
-        return wx.Rect(self.Pos.x + (self.Size[0] - text_width) / 2,
+        return wx.Rect(self.Pos.x + (self.Size[0] - text_width) // 2,
                        self.Pos.y - (text_height + 2),
                        text_width,
                        text_height)
@@ -160,9 +162,9 @@
         # Calculate the size for the connector lines
         lines = max(len(self.Inputs), len(self.Outputs))
         if lines > 0:
-            linesize = max((self.Size[1] - BLOCK_LINE_SIZE) / lines, BLOCK_LINE_SIZE)
+            linesize = max((self.Size[1] - BLOCK_LINE_SIZE) // lines, BLOCK_LINE_SIZE)
             # Update inputs and outputs positions
-            position = BLOCK_LINE_SIZE + linesize / 2
+            position = BLOCK_LINE_SIZE + linesize // 2
             for i in xrange(lines):
                 if scaling is not None:
                     ypos = round_scaling(self.Pos.y + position, scaling[1]) - self.Pos.y
@@ -478,9 +480,9 @@
         # Draw a rectangle with the block size
         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
         # Draw block name and block type
-        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) // 2,
                     self.Pos.y - (name_size[1] + 2))
-        type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) / 2,
+        type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) // 2,
                     self.Pos.y + 5)
         dc.DrawText(self.Name, name_pos[0], name_pos[1])
         dc.DrawText(self.Type, type_pos[0], type_pos[1])
@@ -591,7 +593,7 @@
             bbx_width = self.Size[0] + 2 * CONNECTOR_SIZE
         else:
             bbx_width = self.Size[0] + CONNECTOR_SIZE
-        bbx_x = min(bbx_x, self.Pos.x + (self.Size[0] - self.NameSize[0]) / 2)
+        bbx_x = min(bbx_x, self.Pos.x + (self.Size[0] - self.NameSize[0]) // 2)
         bbx_width = max(bbx_width, self.NameSize[0])
         bbx_height = self.Size[1]
         if self.ExecutionOrder != 0:
@@ -604,9 +606,9 @@
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
         if scaling is not None:
-            position = round_scaling(self.Pos.y + self.Size[1] / 2, scaling[1]) - self.Pos.y
-        else:
-            position = self.Size[1] / 2
+            position = round_scaling(self.Pos.y + self.Size[1] // 2, scaling[1]) - self.Pos.y
+        else:
+            position = self.Size[1] // 2
         if self.Input:
             self.Input.SetPosition(wx.Point(0, position))
         if self.Output:
@@ -777,8 +779,8 @@
             name_size = self.NameSize
             executionorder_size = self.ExecutionOrderSize
 
-        text_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
-                    self.Pos.y + (self.Size[1] - name_size[1]) / 2)
+        text_pos = (self.Pos.x + (self.Size[0] - name_size[0]) // 2,
+                    self.Pos.y + (self.Size[1] - name_size[1]) // 2)
         # Draw a rectangle with the variable size
         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
         # Draw variable name
@@ -876,9 +878,9 @@
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
         if scaling is not None:
-            position = round_scaling(self.Pos.y + self.Size[1] / 2, scaling[1]) - self.Pos.y
-        else:
-            position = self.Size[1] / 2
+            position = round_scaling(self.Pos.y + self.Size[1] // 2, scaling[1]) - self.Pos.y
+        else:
+            position = self.Size[1] // 2
         if self.Type == CONNECTOR:
             self.Connector.SetPosition(wx.Point(0, position))
         else:
@@ -1017,18 +1019,18 @@
 
         # Draw a rectangle with the connection size with arrows inside
         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
-        arrowsize = min(self.Size[1] / 2, (self.Size[0] - name_size[0] - 10) / 2)
+        arrowsize = min(self.Size[1] // 2, (self.Size[0] - name_size[0] - 10) // 2)
         dc.DrawLine(self.Pos.x, self.Pos.y, self.Pos.x + arrowsize,
-                    self.Pos.y + self.Size[1] / 2)
-        dc.DrawLine(self.Pos.x + arrowsize, self.Pos.y + self.Size[1] / 2,
+                    self.Pos.y + self.Size[1] // 2)
+        dc.DrawLine(self.Pos.x + arrowsize, self.Pos.y + self.Size[1] // 2,
                     self.Pos.x, self.Pos.y + self.Size[1])
         dc.DrawLine(self.Pos.x + self.Size[0] - arrowsize, self.Pos.y,
-                    self.Pos.x + self.Size[0], self.Pos.y + self.Size[1] / 2)
-        dc.DrawLine(self.Pos.x + self.Size[0], self.Pos.y + self.Size[1] / 2,
+                    self.Pos.x + self.Size[0], self.Pos.y + self.Size[1] // 2)
+        dc.DrawLine(self.Pos.x + self.Size[0], self.Pos.y + self.Size[1] // 2,
                     self.Pos.x + self.Size[0] - arrowsize, self.Pos.y + self.Size[1])
         # Draw connection name
-        text_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
-                    self.Pos.y + (self.Size[1] - name_size[1]) / 2)
+        text_pos = (self.Pos.x + (self.Size[0] - name_size[0]) // 2,
+                    self.Pos.y + (self.Size[1] - name_size[1]) // 2)
         dc.DrawText(self.Name, text_pos[0], text_pos[1])
         # Draw connector
         if self.Connector:
--- a/graphics/GraphicCommons.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/graphics/GraphicCommons.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,8 +24,11 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 from math import *
-from types import *
+from future.builtins import round
+from six import string_types
+from six.moves import xrange
 
 import wx
 from graphics.ToolTipProducer import ToolTipProducer
@@ -115,7 +118,7 @@
 
 
 def round_scaling(x, n, constraint=0):
-    fraction = float(x) / float(n)
+    fraction = x / n
     if constraint == -1:
         xround = int(fraction)
     else:
@@ -185,8 +188,8 @@
     """
     pos = event.GetLogicalPosition(dc)
     if scaling:
-        pos.x = round(float(pos.x) / float(scaling[0])) * scaling[0]
-        pos.y = round(float(pos.y) / float(scaling[1])) * scaling[1]
+        pos.x = round(pos.x / scaling[0]) * scaling[0]
+        pos.y = round(pos.y / scaling[1]) * scaling[1]
     return pos
 
 
@@ -434,11 +437,11 @@
         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
 
         left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
-        center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
+        center = (self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2
         right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
 
         top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
-        middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
+        middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE // 2
         bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
 
         extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top)
@@ -682,11 +685,11 @@
                 dc.SetBrush(wx.BLACK_BRUSH)
 
                 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
-                center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
+                center = (self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2
                 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
 
                 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
-                middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
+                middle = (self.BoundingBox.y + self.BoundingBox.height // 2) * scaley - HANDLE_SIZE // 2
                 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
 
                 for x, y in [(left, top), (center, top), (right, top),
@@ -858,13 +861,13 @@
                 if horizontally == ALIGN_LEFT:
                     movex = minx - posx
                 elif horizontally == ALIGN_CENTER:
-                    movex = (maxx + minx - width) / 2 - posx
+                    movex = (maxx + minx - width) // 2 - posx
                 elif horizontally == ALIGN_RIGHT:
                     movex = maxx - width - posx
                 if vertically == ALIGN_TOP:
                     movey = miny - posy
                 elif vertically == ALIGN_MIDDLE:
-                    movey = (maxy + miny - height) / 2 - posy
+                    movey = (maxy + miny - height) // 2 - posy
                 elif vertically == ALIGN_BOTTOM:
                     movey = maxy - height - posy
                 if movex != 0 or movey != 0:
@@ -1079,14 +1082,14 @@
                 y -= 5
                 height += 5
         rect = wx.Rect(x - abs(movex), y - abs(movey), width + 2 * abs(movex), height + 2 * abs(movey))
-        if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
+        if self.ValueSize is None and isinstance(self.ComputedValue, string_types):
             self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
         if self.ValueSize is not None:
             width, height = self.ValueSize
             rect = rect.Union(
                 wx.Rect(
                     parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] +
-                    width * (self.Direction[0] - 1) / 2,
+                    width * (self.Direction[0] - 1) // 2,
                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] +
                     height * (self.Direction[1] - 1),
                     width, height))
@@ -1161,7 +1164,7 @@
                 self.Parent.ElementNeedRefresh(self)
 
     def GetComputedValue(self):
-        if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
+        if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, bool):
             return self.Value
         return None
 
@@ -1198,7 +1201,7 @@
         current = False
         for wire, _handle in self.Wires:
             value = wire.GetValue()
-            if current != "undefined" and isinstance(value, BooleanType):
+            if current != "undefined" and isinstance(value, bool):
                 current |= wire.GetValue()
             elif value == "undefined":
                 current = "undefined"
@@ -1470,7 +1473,7 @@
         else:
             if not self.Valid:
                 dc.SetPen(MiterPen(wx.RED))
-            elif isinstance(self.Value, BooleanType) and self.Value:
+            elif isinstance(self.Value, bool) and self.Value:
                 if self.Forced:
                     dc.SetPen(MiterPen(wx.CYAN))
                 else:
@@ -1491,9 +1494,9 @@
 
         if self.Negated:
             # If connector is negated, draw a circle
-            xcenter = parent_pos[0] + self.Pos.x + (CONNECTOR_SIZE * self.Direction[0]) / 2
-            ycenter = parent_pos[1] + self.Pos.y + (CONNECTOR_SIZE * self.Direction[1]) / 2
-            dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE / 2)
+            xcenter = parent_pos[0] + self.Pos.x + (CONNECTOR_SIZE * self.Direction[0]) // 2
+            ycenter = parent_pos[1] + self.Pos.y + (CONNECTOR_SIZE * self.Direction[1]) // 2
+            dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE // 2)
         else:
             xstart = parent_pos[0] + self.Pos.x
             ystart = parent_pos[1] + self.Pos.y
@@ -1518,13 +1521,13 @@
                 yend = ystart + CONNECTOR_SIZE * self.Direction[1]
                 dc.DrawLine(xstart + self.Direction[0], ystart + self.Direction[1], xend, yend)
         if self.Direction[0] != 0:
-            ytext = parent_pos[1] + self.Pos.y - name_size[1] / 2
+            ytext = parent_pos[1] + self.Pos.y - name_size[1] // 2
             if self.Direction[0] < 0:
                 xtext = parent_pos[0] + self.Pos.x + 5
             else:
                 xtext = parent_pos[0] + self.Pos.x - (name_size[0] + 5)
         if self.Direction[1] != 0:
-            xtext = parent_pos[0] + self.Pos.x - name_size[0] / 2
+            xtext = parent_pos[0] + self.Pos.x - name_size[0] // 2
             if self.Direction[1] < 0:
                 ytext = parent_pos[1] + self.Pos.y + 5
             else:
@@ -1534,16 +1537,16 @@
         if not getattr(dc, "printing", False):
             DrawHighlightedText(dc, self.Name, self.Highlights, xtext, ytext)
 
-        if self.Value is not None and not isinstance(self.Value, BooleanType) and self.Value != "undefined":
+        if self.Value is not None and not isinstance(self.Value, bool) and self.Value != "undefined":
             dc.SetFont(self.ParentBlock.Parent.GetMiniFont())
             dc.SetTextForeground(wx.NamedColour("purple"))
-            if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
+            if self.ValueSize is None and isinstance(self.ComputedValue, string_types):
                 self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
             if self.ValueSize is not None:
                 width, height = self.ValueSize
                 dc.DrawText(self.ComputedValue,
                             parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] +
-                            width * (self.Direction[0] - 1) / 2,
+                            width * (self.Direction[0] - 1) // 2,
                             parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] +
                             height * (self.Direction[1] - 1))
             dc.SetFont(self.ParentBlock.Parent.GetFont())
@@ -1605,22 +1608,22 @@
             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
         if self.EndConnected:
             rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey))
-        if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
+        if self.ValueSize is None and isinstance(self.ComputedValue, string_types):
             self.ValueSize = self.Parent.GetMiniTextExtent(self.ComputedValue)
         if self.ValueSize is not None:
             width, height = self.ValueSize
             if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4:
-                x = self.Points[0].x + width * self.StartPoint[1][0] / 2
+                x = self.Points[0].x + width * self.StartPoint[1][0] // 2
                 y = self.Points[0].y + height * (self.StartPoint[1][1] - 1)
                 rect = rect.Union(wx.Rect(x, y, width, height))
-                x = self.Points[-1].x + width * self.EndPoint[1][0] / 2
+                x = self.Points[-1].x + width * self.EndPoint[1][0] // 2
                 y = self.Points[-1].y + height * (self.EndPoint[1][1] - 1)
                 rect = rect.Union(wx.Rect(x, y, width, height))
             else:
-                middle = len(self.Segments) / 2 + len(self.Segments) % 2 - 1
-                x = (self.Points[middle].x + self.Points[middle + 1].x - width) / 2
+                middle = len(self.Segments) // 2 + len(self.Segments) % 2 - 1
+                x = (self.Points[middle].x + self.Points[middle + 1].x - width) // 2
                 if self.BoundingBox[3] > height and self.Segments[middle] in [NORTH, SOUTH]:
-                    y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
+                    y = (self.Points[middle].y + self.Points[middle + 1].y - height) // 2
                 else:
                     y = self.Points[middle].y - height
                 rect = rect.Union(wx.Rect(x, y, width, height))
@@ -1754,7 +1757,7 @@
                 self.Parent.ElementNeedRefresh(self)
 
     def GetComputedValue(self):
-        if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
+        if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, bool):
             return self.Value
         return None
 
@@ -1786,7 +1789,7 @@
                 self.EndConnected.RefreshValue()
             if self.Visible:
                 self.Parent.ElementNeedRefresh(self)
-            if isinstance(value, BooleanType) and self.StartConnected is not None:
+            if isinstance(value, bool) and self.StartConnected is not None:
                 block = self.StartConnected.GetParentBlock()
                 block.SpreadCurrent()
 
@@ -2091,9 +2094,9 @@
                         # Current point is positioned in the middle of start point
                         # and end point on the current direction and a point is added
                         if self.Segments[0][0] != 0:
-                            self.Points[1].x = (end.x + start.x) / 2
+                            self.Points[1].x = (end.x + start.x) // 2
                         if self.Segments[0][1] != 0:
-                            self.Points[1].y = (end.y + start.y) / 2
+                            self.Points[1].y = (end.y + start.y) // 2
                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
                         self.Segments.insert(2, DirectionChoice(
                             (self.Segments[1][1],
@@ -2135,9 +2138,9 @@
                                 # Current point is positioned in the middle of previous point
                                 # and end point on the current direction and a point is added
                                 if self.Segments[1][0] != 0:
-                                    self.Points[2].x = (self.Points[1].x + end.x) / 2
+                                    self.Points[2].x = (self.Points[1].x + end.x) // 2
                                 if self.Segments[1][1] != 0:
-                                    self.Points[2].y = (self.Points[1].y + end.y) / 2
+                                    self.Points[2].y = (self.Points[1].y + end.y) // 2
                                 self.Points.insert(3, wx.Point(self.Points[2].x, self.Points[2].y))
                                 self.Segments.insert(
                                     3,
@@ -2159,9 +2162,9 @@
                             # Current point is positioned in the middle of previous point
                             # and end point on the current direction
                             if self.Segments[i - 1][0] != 0:
-                                self.Points[i].x = (end.x + self.Points[i - 1].x) / 2
+                                self.Points[i].x = (end.x + self.Points[i - 1].x) // 2
                             if self.Segments[i - 1][1] != 0:
-                                self.Points[i].y = (end.y + self.Points[i - 1].y) / 2
+                                self.Points[i].y = (end.y + self.Points[i - 1].y) // 2
                         # A point is added
                         self.Points.insert(i + 1, wx.Point(self.Points[i].x, self.Points[i].y))
                         self.Segments.insert(
@@ -2241,9 +2244,9 @@
                         dir = self.EndPoint[1]
                     else:
                         dir = (0, 0)
-                    pointx = max(-dir[0] * MIN_SEGMENT_SIZE, min(int(round(point[0] * width / float(max(lastwidth, 1)))),
+                    pointx = max(-dir[0] * MIN_SEGMENT_SIZE, min(int(round(point[0] * width / max(lastwidth, 1))),
                                                                  width - dir[0] * MIN_SEGMENT_SIZE))
-                    pointy = max(-dir[1] * MIN_SEGMENT_SIZE, min(int(round(point[1] * height / float(max(lastheight, 1)))),
+                    pointy = max(-dir[1] * MIN_SEGMENT_SIZE, min(int(round(point[1] * height / max(lastheight, 1))),
                                                                  height - dir[1] * MIN_SEGMENT_SIZE))
                     self.Points[i] = wx.Point(minx + x + pointx, miny + y + pointy)
             self.StartPoint[0] = self.Points[0]
@@ -2265,8 +2268,8 @@
             # during a resize dragging
             for i, point in enumerate(self.RealPoints):
                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
-                    point[0] = point[0] * width / float(max(lastwidth, 1))
-                    point[1] = point[1] * height / float(max(lastheight, 1))
+                    point[0] = point[0] * width / max(lastwidth, 1)
+                    point[1] = point[1] * height / max(lastheight, 1)
             # Calculate the correct position of the points from real points
             for i, point in enumerate(self.RealPoints):
                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
@@ -2398,9 +2401,9 @@
                 pointx = self.Points[segment].x
                 pointy = self.Points[segment].y
                 if dir[0] != 0:
-                    pointx = (self.Points[segment].x + self.Points[segment + 1].x) / 2
+                    pointx = (self.Points[segment].x + self.Points[segment + 1].x) // 2
                 if dir[1] != 0:
-                    pointy = (self.Points[segment].y + self.Points[segment + 1].y) / 2
+                    pointy = (self.Points[segment].y + self.Points[segment + 1].y) // 2
                 self.Points.insert(segment + 1, wx.Point(pointx, pointy))
                 self.Segments.insert(segment + 1, (dir[1], dir[0]))
                 self.Points.insert(segment + 2, wx.Point(pointx, pointy))
@@ -2409,11 +2412,11 @@
                 p1x = p2x = self.Points[segment].x
                 p1y = p2y = self.Points[segment].y
                 if dir[0] != 0:
-                    p1x = (2 * self.Points[segment].x + self.Points[segment + 1].x) / 3
-                    p2x = (self.Points[segment].x + 2 * self.Points[segment + 1].x) / 3
+                    p1x = (2 * self.Points[segment].x + self.Points[segment + 1].x) // 3
+                    p2x = (self.Points[segment].x + 2 * self.Points[segment + 1].x) // 3
                 if dir[1] != 0:
-                    p1y = (2 * self.Points[segment].y + self.Points[segment + 1].y) / 3
-                    p2y = (self.Points[segment].y + 2 * self.Points[segment + 1].y) / 3
+                    p1y = (2 * self.Points[segment].y + self.Points[segment + 1].y) // 3
+                    p2y = (self.Points[segment].y + 2 * self.Points[segment + 1].y) // 3
                 self.Points.insert(segment + 1, wx.Point(p1x, p1y))
                 self.Segments.insert(segment + 1, (dir[1], dir[0]))
                 self.Points.insert(segment + 2, wx.Point(p1x, p1y))
@@ -2476,9 +2479,9 @@
         if event.ControlDown():
             direction = (self.StartPoint[1], self.EndPoint[1])
             if direction in [(EAST, WEST), (WEST, EAST)]:
-                avgy = (self.StartPoint[0].y + self.EndPoint[0].y) / 2
+                avgy = (self.StartPoint[0].y + self.EndPoint[0].y) // 2
                 if scaling is not None:
-                    avgy = round(float(avgy) / scaling[1]) * scaling[1]
+                    avgy = round(avgy / scaling[1]) * scaling[1]
                 if self.StartConnected is not None:
                     movey = avgy - self.StartPoint[0].y
                     startblock = self.StartConnected.GetParentBlock()
@@ -2497,9 +2500,9 @@
                     self.MoveEndPoint(wx.Point(self.EndPoint[0].x, avgy))
                 self.Parent.RefreshBuffer()
             elif direction in [(NORTH, SOUTH), (SOUTH, NORTH)]:
-                avgx = (self.StartPoint[0].x + self.EndPoint[0].x) / 2
+                avgx = (self.StartPoint[0].x + self.EndPoint[0].x) // 2
                 if scaling is not None:
-                    avgx = round(float(avgx) / scaling[0]) * scaling[0]
+                    avgx = round(avgx / scaling[0]) * scaling[0]
                 if self.StartConnected is not None:
                     movex = avgx - self.StartPoint[0].x
                     startblock = self.StartConnected.GetParentBlock()
@@ -2679,7 +2682,7 @@
         if not self.Valid:
             dc.SetPen(MiterPen(wx.RED))
             dc.SetBrush(wx.RED_BRUSH)
-        elif isinstance(self.Value, BooleanType) and self.Value:
+        elif isinstance(self.Value, bool) and self.Value:
             if self.Forced:
                 dc.SetPen(MiterPen(wx.CYAN))
                 dc.SetBrush(wx.CYAN_BRUSH)
@@ -2717,25 +2720,25 @@
                 end = 1
             dc.DrawLine(self.Points[self.SelectedSegment].x - 1, self.Points[self.SelectedSegment].y,
                         self.Points[self.SelectedSegment + 1].x + end, self.Points[self.SelectedSegment + 1].y)
-        if self.Value is not None and not isinstance(self.Value, BooleanType) and self.Value != "undefined":
+        if self.Value is not None and not isinstance(self.Value, bool) and self.Value != "undefined":
             dc.SetFont(self.Parent.GetMiniFont())
             dc.SetTextForeground(wx.NamedColour("purple"))
-            if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
+            if self.ValueSize is None and isinstance(self.ComputedValue, string_types):
                 self.ValueSize = self.Parent.GetMiniTextExtent(self.ComputedValue)
             if self.ValueSize is not None:
                 width, height = self.ValueSize
                 if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4:
-                    x = self.Points[0].x + width * (self.StartPoint[1][0] - 1) / 2
+                    x = self.Points[0].x + width * (self.StartPoint[1][0] - 1) // 2
                     y = self.Points[0].y + height * (self.StartPoint[1][1] - 1)
                     dc.DrawText(self.ComputedValue, x, y)
-                    x = self.Points[-1].x + width * (self.EndPoint[1][0] - 1) / 2
+                    x = self.Points[-1].x + width * (self.EndPoint[1][0] - 1) // 2
                     y = self.Points[-1].y + height * (self.EndPoint[1][1] - 1)
                     dc.DrawText(self.ComputedValue, x, y)
                 else:
-                    middle = len(self.Segments) / 2 + len(self.Segments) % 2 - 1
-                    x = (self.Points[middle].x + self.Points[middle + 1].x - width) / 2
+                    middle = len(self.Segments) // 2 + len(self.Segments) % 2 - 1
+                    x = (self.Points[middle].x + self.Points[middle + 1].x - width) // 2
                     if self.BoundingBox[3] > height and self.Segments[middle] in [NORTH, SOUTH]:
-                        y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
+                        y = (self.Points[middle].y + self.Points[middle + 1].y - height) // 2
                     else:
                         y = self.Points[middle].y - height
                     dc.DrawText(self.ComputedValue, x, y)
--- a/graphics/LD_Objects.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/graphics/LD_Objects.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,10 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import wx
+from future.builtins import round
+from six.moves import xrange
 
 from graphics.GraphicCommons import *
 from graphics.DebugDataConsumer import DebugDataConsumer
@@ -48,7 +51,7 @@
         self.Connectors = []
         self.RealConnectors = None
         self.Id = id
-        self.Extensions = [LD_LINE_SIZE / 2, LD_LINE_SIZE / 2]
+        self.Extensions = [LD_LINE_SIZE // 2, LD_LINE_SIZE // 2]
         self.SetType(type, connectors)
 
     def Flush(self):
@@ -183,14 +186,14 @@
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
         height = self.Size[1] - self.Extensions[0] - self.Extensions[1]
-        interval = float(height) / float(max(len(self.Connectors) - 1, 1))
+        interval = height / max(len(self.Connectors) - 1, 1)
         for i, connector in enumerate(self.Connectors):
             if self.RealConnectors:
                 position = self.Extensions[0] + int(round(self.RealConnectors[i] * height))
             else:
                 position = self.Extensions[0] + int(round(i * interval))
             if scaling is not None:
-                position = round(float(self.Pos.y + position) / float(scaling[1])) * scaling[1] - self.Pos.y
+                position = round((self.Pos.y + position) / scaling[1]) * scaling[1] - self.Pos.y
             if self.Type == LEFTRAIL:
                 connector.SetPosition(wx.Point(self.Size[0], position))
             elif self.Type == RIGHTRAIL:
@@ -250,7 +253,7 @@
         if height > 0:
             for connector in self.Connectors:
                 position = connector.GetRelPosition()
-                self.RealConnectors.append(max(0., min(float(position.y - self.Extensions[0]) / float(height), 1.)))
+                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)))
         else:
@@ -311,7 +314,7 @@
             movey = max(-self.BoundingBox.y, movey)
             if scaling is not None:
                 position = handle.GetRelPosition()
-                movey = round(float(self.Pos.y + position.y + movey) / float(scaling[1])) * scaling[1] - self.Pos.y - position.y
+                movey = round((self.Pos.y + position.y + movey) / scaling[1]) * scaling[1] - self.Pos.y - position.y
             self.MoveConnector(handle, movey)
             return 0, movey
         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
@@ -362,8 +365,8 @@
         self.Size = wx.Size(LD_ELEMENT_SIZE[0], LD_ELEMENT_SIZE[1])
         self.Highlights = {}
         # Create an input and output connector
-        self.Input = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2 + 1), WEST)
-        self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
+        self.Input = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] // 2 + 1), WEST)
+        self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] // 2 + 1), EAST)
         self.PreviousValue = False
         self.PreviousSpreading = False
         self.RefreshNameSize()
@@ -492,7 +495,7 @@
         text_width, text_height = self.Parent.GetTextExtent(self.Name)
         # Calculate the bounding box size
         if self.Name != "":
-            bbx_x = self.Pos.x - max(0, (text_width - self.Size[0]) / 2)
+            bbx_x = self.Pos.x - max(0, (text_width - self.Size[0]) // 2)
             bbx_width = max(self.Size[0], text_width)
             bbx_y = self.Pos.y - (text_height + 2)
             bbx_height = self.Size[1] + (text_height + 2)
@@ -540,9 +543,9 @@
     # Refresh the positions of the block connectors
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
-        position = self.Size[1] / 2 + 1
+        position = self.Size[1] // 2 + 1
         if scaling is not None:
-            position = round(float(self.Pos.y + position) / float(scaling[1])) * scaling[1] - self.Pos.y
+            position = round((self.Pos.y + position) / scaling[1]) * scaling[1] - self.Pos.y
         self.Input.SetPosition(wx.Point(0, position))
         self.Output.SetPosition(wx.Point(self.Size[0], position))
         self.RefreshConnected()
@@ -669,13 +672,13 @@
         dc.DrawRectangle(self.Pos.x, self.Pos.y, 2, self.Size[1] + 1)
         dc.DrawRectangle(self.Pos.x + self.Size[0] - 1, self.Pos.y, 2, self.Size[1] + 1)
         # Draw contact name
-        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) // 2,
                     self.Pos.y - (name_size[1] + 2))
         dc.DrawText(self.Name, name_pos[0], name_pos[1])
         # Draw the modifier symbol in the middle of contact
         if typetext != "":
-            type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) / 2 + 1,
-                        self.Pos.y + (self.Size[1] - type_size[1]) / 2)
+            type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) // 2 + 1,
+                        self.Pos.y + (self.Size[1] - type_size[1]) // 2)
             dc.DrawText(typetext, type_pos[0], type_pos[1])
         # Draw input and output connectors
         self.Input.Draw(dc)
@@ -708,8 +711,8 @@
         self.Size = wx.Size(LD_ELEMENT_SIZE[0], LD_ELEMENT_SIZE[1])
         self.Highlights = {}
         # Create an input and output connector
-        self.Input = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2 + 1), WEST)
-        self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
+        self.Input = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] // 2 + 1), WEST)
+        self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] // 2 + 1), EAST)
         self.Value = None
         self.PreviousValue = False
         self.RefreshNameSize()
@@ -812,7 +815,7 @@
         text_width, text_height = self.Parent.GetTextExtent(self.Name)
         # Calculate the bounding box size
         if self.Name != "":
-            bbx_x = self.Pos.x - max(0, (text_width - self.Size[0]) / 2)
+            bbx_x = self.Pos.x - max(0, (text_width - self.Size[0]) // 2)
             bbx_width = max(self.Size[0], text_width)
             bbx_y = self.Pos.y - (text_height + 2)
             bbx_height = self.Size[1] + (text_height + 2)
@@ -860,9 +863,9 @@
     # Refresh the positions of the block connectors
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
-        position = self.Size[1] / 2 + 1
+        position = self.Size[1] // 2 + 1
         if scaling is not None:
-            position = round(float(self.Pos.y + position) / float(scaling[1])) * scaling[1] - self.Pos.y
+            position = round((self.Pos.y + position) / scaling[1]) * scaling[1] - self.Pos.y
         self.Input.SetPosition(wx.Point(0, position))
         self.Output.SetPosition(wx.Point(self.Size[0], position))
         self.RefreshConnected()
@@ -992,19 +995,19 @@
                     dc.SetPen(MiterPen(wx.GREEN))
                 else:
                     dc.SetPen(MiterPen(wx.BLACK))
-                dc.DrawPoint(self.Pos.x + 1, self.Pos.y + self.Size[1] / 2 + 1)
+                dc.DrawPoint(self.Pos.x + 1, self.Pos.y + self.Size[1] // 2 + 1)
             name_size = self.NameSize
             if typetext != "":
                 type_size = self.TypeSize
 
         # Draw coil name
-        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) // 2,
                     self.Pos.y - (name_size[1] + 2))
         dc.DrawText(self.Name, name_pos[0], name_pos[1])
         # Draw the modifier symbol in the middle of coil
         if typetext != "":
-            type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) / 2 + 1,
-                        self.Pos.y + (self.Size[1] - type_size[1]) / 2)
+            type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) // 2 + 1,
+                        self.Pos.y + (self.Size[1] - type_size[1]) // 2)
             dc.DrawText(typetext, type_pos[0], type_pos[1])
         # Draw input and output connectors
         self.Input.Draw(dc)
--- a/graphics/SFC_Objects.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/graphics/SFC_Objects.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,7 +24,11 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
+from future.builtins import round
+
 import wx
+from six.moves import xrange
 
 from graphics.GraphicCommons import *
 from graphics.DebugDataConsumer import DebugDataConsumer
@@ -58,7 +62,7 @@
         self.Size = wx.Size(SFC_STEP_DEFAULT_SIZE[0], SFC_STEP_DEFAULT_SIZE[1])
         # Create an input and output connector
         if not self.Initial:
-            self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH)
+            self.Input = Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH)
         else:
             self.Input = None
         self.Output = None
@@ -170,7 +174,7 @@
     # Add output connector to step
     def AddInput(self):
         if not self.Input:
-            self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH)
+            self.Input = Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH)
             self.RefreshBoundingBox()
 
     # Remove output connector from step
@@ -183,7 +187,7 @@
     # Add output connector to step
     def AddOutput(self):
         if not self.Output:
-            self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)
+            self.Output = Connector(self, "", None, wx.Point(self.Size[0] // 2, self.Size[1]), SOUTH, onlyone=True)
             self.RefreshBoundingBox()
 
     # Remove output connector from step
@@ -196,7 +200,7 @@
     # Add action connector to step
     def AddAction(self):
         if not self.Action:
-            self.Action = Connector(self, "", None, wx.Point(self.Size[0], self.Size[1] / 2), EAST, onlyone=True)
+            self.Action = Connector(self, "", None, wx.Point(self.Size[0], self.Size[1] // 2), EAST, onlyone=True)
             self.RefreshBoundingBox()
 
     # Remove action connector from step
@@ -231,11 +235,11 @@
     # Refresh the positions of the step connectors
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
-        horizontal_pos = self.Size[0] / 2
-        vertical_pos = self.Size[1] / 2
+        horizontal_pos = self.Size[0] // 2
+        vertical_pos = self.Size[1] // 2
         if scaling is not None:
-            horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
-            vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
+            horizontal_pos = round((self.Pos.x + horizontal_pos) / scaling[0]) * scaling[0] - self.Pos.x
+            vertical_pos = round((self.Pos.y + vertical_pos) / scaling[1]) * scaling[1] - self.Pos.y
         # Update input position if it exists
         if self.Input:
             self.Input.SetPosition(wx.Point(horizontal_pos, 0))
@@ -362,7 +366,7 @@
 
     # Updates the step size
     def UpdateSize(self, width, height):
-        diffx = self.Size.GetWidth() / 2 - width / 2
+        diffx = self.Size.GetWidth() // 2 - width // 2
         diffy = height - self.Size.GetHeight()
         self.Move(diffx, 0)
         Graphic_Element.SetSize(self, width, height)
@@ -462,8 +466,8 @@
             movex = max(-self.BoundingBox.x, movex)
             movey = max(-self.BoundingBox.y, movey)
             if scaling is not None:
-                movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
-                movey = round(float(self.Pos.y + movey) / float(scaling[1])) * scaling[1] - self.Pos.y
+                movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
+                movey = round((self.Pos.y + movey) / scaling[1]) * scaling[1] - self.Pos.y
             if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
                 self.Move(movex, movey)
                 self.RefreshConnected()
@@ -556,8 +560,8 @@
         if self.Initial:
             dc.DrawRectangle(self.Pos.x + 2, self.Pos.y + 2, self.Size[0] - 3, self.Size[1] - 3)
         # Draw step name
-        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
-                    self.Pos.y + (self.Size[1] - name_size[1]) / 2)
+        name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) // 2,
+                    self.Pos.y + (self.Size[1] - name_size[1]) // 2)
         dc.DrawText(self.Name, name_pos[0], name_pos[1])
         # Draw input and output connectors
         if self.Input:
@@ -590,8 +594,8 @@
         self.Priority = 0
         self.Size = wx.Size(SFC_TRANSITION_SIZE[0], SFC_TRANSITION_SIZE[1])
         # Create an input and output connector
-        self.Input = Connector(self,  "", None, wx.Point(self.Size[0] / 2, 0),            NORTH, onlyone=True)
-        self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)
+        self.Input = Connector(self,  "", None, wx.Point(self.Size[0] // 2, 0),            NORTH, onlyone=True)
+        self.Output = Connector(self, "", None, wx.Point(self.Size[0] // 2, self.Size[1]), SOUTH, onlyone=True)
         self.SetType(type, condition)
         self.SetPriority(priority)
         self.Highlights = {}
@@ -712,7 +716,7 @@
             # Calculate the bounding box of the condition outside the transition
             text_width, text_height = self.ConditionSize
             text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 5,
-                               self.Pos.y + (self.Size[1] - text_height) / 2,
+                               self.Pos.y + (self.Size[1] - text_height) // 2,
                                text_width,
                                text_height)
             test_text = text_bbx.InsideXY(pt.x, pt.y)
@@ -734,8 +738,8 @@
             text_width, text_height = self.ConditionSize
             # Calculate the bounding box size
             bbx_width = max(bbx_width, self.Size[0] + 5 + text_width)
-            bbx_y = min(bbx_y, self.Pos.y - max(0, (text_height - self.Size[1]) / 2))
-            bbx_height = max(bbx_height, self.Pos.y - bbx_y + (self.Size[1] + text_height) / 2)
+            bbx_y = min(bbx_y, self.Pos.y - max(0, (text_height - self.Size[1]) // 2))
+            bbx_height = max(bbx_height, self.Pos.y - bbx_y + (self.Size[1] + text_height) // 2)
         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
 
     # Returns the connector connected to input
@@ -755,11 +759,11 @@
     # Refresh the positions of the transition connectors
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
-        horizontal_pos = self.Size[0] / 2
-        vertical_pos = self.Size[1] / 2
+        horizontal_pos = self.Size[0] // 2
+        vertical_pos = self.Size[1] // 2
         if scaling is not None:
-            horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
-            vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
+            horizontal_pos = round((self.Pos.x + horizontal_pos) / scaling[0]) * scaling[0] - self.Pos.x
+            vertical_pos = round((self.Pos.y + vertical_pos) / scaling[1]) * scaling[1] - self.Pos.y
         # Update input position
         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
         # Update output position
@@ -821,7 +825,7 @@
                 self.Condition.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
             self.Type = type
             if type == "connection":
-                self.Condition = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2), WEST)
+                self.Condition = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] // 2), WEST)
             else:
                 if condition is None:
                     condition = ""
@@ -916,7 +920,7 @@
         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
             movex = max(-self.BoundingBox.x, movex)
             if scaling is not None:
-                movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
+                movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
             self.Move(movex, 0)
             self.RefreshInputPosition()
             self.RefreshOutputPosition()
@@ -1008,7 +1012,7 @@
 
         # Draw plain rectangle for representing the transition
         dc.DrawRectangle(self.Pos.x,
-                         self.Pos.y + (self.Size[1] - SFC_TRANSITION_SIZE[1])/2,
+                         self.Pos.y + (self.Size[1] - SFC_TRANSITION_SIZE[1]) // 2,
                          self.Size[0] + 1,
                          SFC_TRANSITION_SIZE[1] + 1)
         vertical_line_x = self.Input.GetPosition()[0]
@@ -1020,7 +1024,7 @@
             else:
                 condition = "Transition"
             condition_pos = (self.Pos.x + self.Size[0] + 5,
-                             self.Pos.y + (self.Size[1] - condition_size[1]) / 2)
+                             self.Pos.y + (self.Size[1] - condition_size[1]) // 2)
             dc.DrawText(condition, condition_pos[0], condition_pos[1])
         # Draw priority number
         if self.Priority != 0:
@@ -1061,7 +1065,7 @@
         self.Size = wx.Size((number - 1) * SFC_DEFAULT_SEQUENCE_INTERVAL, self.GetMinSize()[1])
         # Create an input and output connector
         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
-            self.Inputs = [Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone=True)]
+            self.Inputs = [Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH, onlyone=True)]
             self.Outputs = []
             for i in xrange(number):
                 self.Outputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone=True))
@@ -1069,7 +1073,7 @@
             self.Inputs = []
             for i in xrange(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.Outputs = [Connector(self, "", None, wx.Point(self.Size[0] // 2, self.Size[1]), SOUTH, onlyone=True)]
         self.Value = None
         self.PreviousValue = None
 
@@ -1284,14 +1288,14 @@
             if self.RealConnectors:
                 input.SetPosition(wx.Point(int(round(self.RealConnectors["Inputs"][i] * width)), 0))
             else:
-                input.SetPosition(wx.Point(int(round(float(position.x)*float(width)/float(self.Size[0]))), 0))
+                input.SetPosition(wx.Point(int(round(position.x*width / self.Size[0])), 0))
             input.MoveConnected()
         for i, output in enumerate(self.Outputs):
             position = output.GetRelPosition()
             if self.RealConnectors:
                 output.SetPosition(wx.Point(int(round(self.RealConnectors["Outputs"][i] * width)), height))
             else:
-                output.SetPosition(wx.Point(int(round(float(position.x)*float(width)/float(self.Size[0]))), height))
+                output.SetPosition(wx.Point(int(round(position.x*width / self.Size[0])), height))
             output.MoveConnected()
         self.Size = wx.Size(width, height)
         self.RefreshBoundingBox()
@@ -1367,10 +1371,10 @@
         self.RealConnectors = {"Inputs": [], "Outputs": []}
         for input in self.Inputs:
             position = input.GetRelPosition()
-            self.RealConnectors["Inputs"].append(float(position.x)/float(self.Size[0]))
+            self.RealConnectors["Inputs"].append(position.x / self.Size[0])
         for output in self.Outputs:
             position = output.GetRelPosition()
-            self.RealConnectors["Outputs"].append(float(position.x)/float(self.Size[0]))
+            self.RealConnectors["Outputs"].append(position.x / self.Size[0])
         Graphic_Element.OnLeftDown(self, event, dc, scaling)
 
     # Method called when a LeftUp event have been generated
@@ -1424,7 +1428,7 @@
         if handle_type == HANDLE_CONNECTOR:
             movex = max(-self.BoundingBox.x, movex)
             if scaling is not None:
-                movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
+                movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
             self.MoveConnector(handle, movex)
             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
                 self.RefreshConnectedPosition(handle)
@@ -1518,7 +1522,7 @@
         self.Size = wx.Size(SFC_JUMP_SIZE[0], SFC_JUMP_SIZE[1])
         self.Highlights = []
         # Create an input and output connector
-        self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone=True)
+        self.Input = Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH, onlyone=True)
         self.Value = None
         self.PreviousValue = None
 
@@ -1585,7 +1589,7 @@
         # Calculate the bounding box of the condition outside the transition
         text_width, text_height = self.TargetSize
         text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 2,
-                           self.Pos.y + (self.Size[1] - text_height) / 2,
+                           self.Pos.y + (self.Size[1] - text_height) // 2,
                            text_width,
                            text_height)
         return text_bbx.InsideXY(pt.x, pt.y) or Graphic_Element.HitTest(self, pt, connectors)
@@ -1608,9 +1612,9 @@
     # Refresh the element connectors position
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
-        horizontal_pos = self.Size[0] / 2
+        horizontal_pos = self.Size[0] // 2
         if scaling is not None:
-            horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
+            horizontal_pos = round((self.Pos.x + horizontal_pos) / scaling[0]) * scaling[0] - self.Pos.x
         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
         self.RefreshConnected()
 
@@ -1684,7 +1688,7 @@
         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
             movex = max(-self.BoundingBox.x, movex)
             if scaling is not None:
-                movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
+                movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
             self.Move(movex, 0)
             self.RefreshInputPosition()
             return movex, 0
@@ -1759,14 +1763,14 @@
             target_size = self.TargetSize
 
         # Draw plain rectangle for representing the divergence
-        dc.DrawLine(self.Pos.x + self.Size[0] / 2, self.Pos.y, self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1])
+        dc.DrawLine(self.Pos.x + self.Size[0] // 2, self.Pos.y, self.Pos.x + self.Size[0] // 2, self.Pos.y + self.Size[1])
         points = [wx.Point(self.Pos.x, self.Pos.y),
-                  wx.Point(self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1] / 3),
+                  wx.Point(self.Pos.x + self.Size[0] // 2, self.Pos.y + self.Size[1] // 3),
                   wx.Point(self.Pos.x + self.Size[0], self.Pos.y),
-                  wx.Point(self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1])]
+                  wx.Point(self.Pos.x + self.Size[0] // 2, self.Pos.y + self.Size[1])]
         dc.DrawPolygon(points)
         target_pos = (self.Pos.x + self.Size[0] + 2,
-                      self.Pos.y + (self.Size[1] - target_size[1]) / 2)
+                      self.Pos.y + (self.Size[1] - target_size[1]) // 2)
         dc.DrawText(self.Target, target_pos[0], target_pos[1])
         # Draw input connector
         if self.Input:
@@ -1794,7 +1798,7 @@
         self.MinSize = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
         self.Highlights = {}
         # Create an input and output connector
-        self.Input = Connector(self, "", None, wx.Point(0, SFC_ACTION_MIN_SIZE[1] / 2), WEST, onlyone=True)
+        self.Input = Connector(self, "", None, wx.Point(0, SFC_ACTION_MIN_SIZE[1] // 2), WEST, onlyone=True)
         self.SetActions(actions)
         self.Value = None
         self.PreviousValue = None
@@ -1842,7 +1846,7 @@
 
     def GetLineSize(self):
         if len(self.Actions) > 0:
-            return self.Size[1] / len(self.Actions)
+            return self.Size[1] // len(self.Actions)
         else:
             return SFC_ACTION_MIN_SIZE[1]
 
@@ -1888,9 +1892,9 @@
     # Refresh the element connectors position
     def RefreshConnectors(self):
         scaling = self.Parent.GetScaling()
-        vertical_pos = SFC_ACTION_MIN_SIZE[1] / 2
+        vertical_pos = SFC_ACTION_MIN_SIZE[1] // 2
         if scaling is not None:
-            vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
+            vertical_pos = round((self.Pos.y + vertical_pos) / scaling[1]) * scaling[1] - self.Pos.y
         self.Input.SetPosition(wx.Point(0, vertical_pos))
         self.RefreshConnected()
 
@@ -1961,7 +1965,7 @@
             if handle_type == HANDLE_MOVE:
                 movex = max(-self.BoundingBox.x, movex)
                 if scaling is not None:
-                    movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
+                    movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
                 wires = self.Input.GetWires()
                 if len(wires) == 1:
                     input_pos = wires[0][0].GetOtherConnected(self.Input).GetPosition(False)
@@ -2032,24 +2036,24 @@
                             self.Pos.x + self.Size[0], self.Pos.y + i * line_size)
             qualifier_size = dc.GetTextExtent(action.qualifier)
             if action.duration != "":
-                qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
-                                 self.Pos.y + i * line_size + line_size / 2 - qualifier_size[1])
+                qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) // 2,
+                                 self.Pos.y + i * line_size + line_size // 2 - qualifier_size[1])
                 duration_size = dc.GetTextExtent(action.duration)
-                duration_pos = (self.Pos.x + (colsize[0] - duration_size[0]) / 2,
-                                self.Pos.y + i * line_size + line_size / 2)
+                duration_pos = (self.Pos.x + (colsize[0] - duration_size[0]) // 2,
+                                self.Pos.y + i * line_size + line_size // 2)
                 dc.DrawText(action.duration, duration_pos[0], duration_pos[1])
             else:
-                qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
-                                 self.Pos.y + i * line_size + (line_size - qualifier_size[1]) / 2)
+                qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) // 2,
+                                 self.Pos.y + i * line_size + (line_size - qualifier_size[1]) // 2)
             dc.DrawText(action.qualifier, qualifier_pos[0], qualifier_pos[1])
             content_size = dc.GetTextExtent(action.value)
-            content_pos = (self.Pos.x + colsize[0] + (colsize[1] - content_size[0]) / 2,
-                           self.Pos.y + i * line_size + (line_size - content_size[1]) / 2)
+            content_pos = (self.Pos.x + colsize[0] + (colsize[1] - content_size[0]) // 2,
+                           self.Pos.y + i * line_size + (line_size - content_size[1]) // 2)
             dc.DrawText(action.value, content_pos[0], content_pos[1])
             if action.indicator != "":
                 indicator_size = dc.GetTextExtent(action.indicator)
-                indicator_pos = (self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - indicator_size[0]) / 2,
-                                 self.Pos.y + i * line_size + (line_size - indicator_size[1]) / 2)
+                indicator_pos = (self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - indicator_size[0]) // 2,
+                                 self.Pos.y + i * line_size + (line_size - indicator_size[1]) // 2)
                 dc.DrawText(action.indicator, indicator_pos[0], indicator_pos[1])
 
             if not getattr(dc, "printing", False):
--- a/i18n/mki18n.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/i18n/mki18n.py	Fri Nov 23 12:13:24 2018 +0100
@@ -84,8 +84,10 @@
 import os
 import sys
 import re
+from builtins import str as text
 import wx
 
+
 # -----------------------------------------------------------------------------
 # Global variables
 # ----------------
@@ -149,7 +151,7 @@
     messages_file.write('\n')
 
     words_found = {}
-    for filepath in appfil_file.xreadlines():
+    for filepath in appfil_file.readlines():
         code_file = open(filepath.strip(), 'r')
         for match in regexp.finditer(code_file.read()):
             word = match.group(1)
@@ -200,7 +202,7 @@
     os.chdir(applicationDirectoryPath)
     filelist = 'app.fil'
     if not os.path.exists(filelist):
-        raise IOError(2, 'No module file: ' % filelist)
+        raise IOError(2, 'No module file: %s' % filelist)
 
     fileout = 'messages.pot'
     # Steps:
@@ -214,10 +216,10 @@
     verbosePrint(verbose, cmd)
     os.system(cmd)
 
-    XSD_STRING_MODEL = re.compile("<xsd\:(?:element|attribute) name=\"([^\"]*)\"[^\>]*\>")
+    XSD_STRING_MODEL = re.compile(r"<xsd\:(?:element|attribute) name=\"([^\"]*)\"[^\>]*\>")
     processCustomFiles(filelist, fileout, XSD_STRING_MODEL, 'Extra XSD strings')
 
-    XML_TC6_STRING_MODEL = re.compile("<documentation>\s*<xhtml\:p><!\[CDATA\[([^\]]*)\]\]></xhtml\:p>\s*</documentation>", re.MULTILINE | re.DOTALL)
+    XML_TC6_STRING_MODEL = re.compile(r"<documentation>\s*<xhtml\:p><!\[CDATA\[([^\]]*)\]\]></xhtml\:p>\s*</documentation>", re.MULTILINE | re.DOTALL)
     processCustomFiles(filelist, fileout, XML_TC6_STRING_MODEL, 'Extra TC6 documentation strings')
 
     # generate messages.po
@@ -487,7 +489,7 @@
     try:
         optionList, pargs = getopt.getopt(sys.argv[1:], validOptions, validLongOptions)
     except getopt.GetoptError as e:
-        printUsage(e[0])
+        printUsage(e)
         sys.exit(1)
     for (opt, val) in optionList:
         if opt == '-h':
@@ -513,7 +515,7 @@
             makePO(appDirPath, option['domain'], option['verbose'])
             exit_code = 0
         except IOError as e:
-            printUsage(e[1] + '\n   You must write a file app.fil that contains the list of all files to parse.')
+            printUsage(text(e) + '\n   You must write a file app.fil that contains the list of all files to parse.')
     if option['mo']:
         makeMO(appDirPath, option['moTarget'], option['domain'], option['verbose'], option['forceEnglish'])
         exit_code = 0
--- a/modbus/mb_utils.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/modbus/mb_utils.py	Fri Nov 23 12:13:24 2018 +0100
@@ -22,6 +22,9 @@
 # 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:
 # key   - string with the description we want in the request plugin GUI
@@ -185,7 +188,7 @@
 {%(buffer)s}, {%(buffer)s}}'''
 
     timeout = int(GetCTVal(child, 4))
-    timeout_s = int(timeout / 1000)
+    timeout_s = timeout // 1000
     timeout_ms = timeout - (timeout_s * 1000)
     timeout_ns = timeout_ms * 1000000
 
--- a/modbus/modbus.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/modbus/modbus.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,8 +25,9 @@
 
 from __future__ import absolute_import
 import os
+from six.moves import xrange
+
 from modbus.mb_utils import *
-
 from ConfigTreeNode import ConfigTreeNode
 from PLCControler import LOCATION_CONFNODE, LOCATION_VAR_MEMORY
 
--- a/plcopen/plcopen.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/plcopen/plcopen.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,10 +25,11 @@
 
 
 from __future__ import absolute_import
-from types import *
+from __future__ import division
 import re
 from collections import OrderedDict
 
+from six.moves import xrange
 from lxml import etree
 
 from xmlclass import *
@@ -77,7 +78,7 @@
     ("SL", True)])
 
 
-FILTER_ADDRESS_MODEL = "(%%[IQM](?:[XBWDL])?)(%s)((?:\.[0-9]+)*)"
+FILTER_ADDRESS_MODEL = r"(%%[IQM](?:[XBWDL])?)(%s)((?:\.[0-9]+)*)"
 
 
 def update_address(address, address_model, new_leading):
@@ -229,8 +230,8 @@
         "http://www.plcopen.org/xml/tc6.xsd",
         "http://www.plcopen.org/xml/tc6_0201")
     for cre, repl in [
-            (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
-            (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
+            (re.compile(r"(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
+            (re.compile(r"(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
         project_xml = cre.sub(repl, project_xml)
 
     try:
@@ -261,9 +262,9 @@
                                 text += "%ds" % time_values[2]
                             if time_values[3] != 0:
                                 if time_values[3] % 1000 != 0:
-                                    text += "%.3fms" % (float(time_values[3]) / 1000)
+                                    text += "%.3fms" % (time_values[3] / 1000)
                                 else:
-                                    text += "%dms" % (time_values[3] / 1000)
+                                    text += "%dms" % (time_values[3] // 1000)
                             task.set("interval", text)
 
                 # Update resources pou instance attributes
@@ -299,7 +300,7 @@
         return tree, error
 
     except Exception as e:
-        return None, e.message
+        return None, str(e)
 
 
 def LoadProject(filepath):
@@ -2874,7 +2875,7 @@
 
 cls = PLCOpenParser.GetElementClass("arrayValue", "value")
 if cls:
-    arrayValue_model = re.compile("([0-9]+)\((.*)\)$")
+    arrayValue_model = re.compile(r"([0-9]+)\((.*)\)$")
     _updateArrayValueValueClass(cls)
 
 # ----------------------------------------------------------------------
--- a/plcopen/structures.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/plcopen/structures.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,9 +24,9 @@
 
 
 from __future__ import absolute_import
-import string
 import re
 from collections import OrderedDict
+from functools import reduce
 
 from plcopen.plcopen import LoadProject
 from plcopen.definitions import *
@@ -104,7 +104,10 @@
     """
     take a .csv file and translate it it a "csv_table"
     """
-    return [map(string.strip, line.split(';')) for line in file.xreadlines()]
+    table = [[column.strip()
+              for column in line.split(';')]
+             for line in file.readlines()]
+    return table
 
 
 def find_section(section_name, table):
@@ -264,7 +267,7 @@
                             Function_decl_copy = Function_decl.copy()
                             Current_section["list"].append(Function_decl_copy)
             else:
-                raise "First function must be in a category"
+                raise ValueError("First function must be in a category")
 
     return Standard_Functions_Decl
 
--- a/py_ext/PythonFileCTNMixin.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/py_ext/PythonFileCTNMixin.py	Fri Nov 23 12:13:24 2018 +0100
@@ -27,8 +27,9 @@
 from __future__ import absolute_import
 import os
 import re
+from builtins import str as text
+
 import util.paths as paths
-
 from xmlclass import GenerateParserFromXSD
 
 from CodeFileTreeNode import CodeFile
@@ -62,8 +63,8 @@
                 'xmlns="http://www.w3.org/2001/XMLSchema"',
                 'xmlns:xhtml="http://www.w3.org/1999/xhtml"')
             for cre, repl in [
-                    (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
-                    (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
+                    (re.compile(r"(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
+                    (re.compile(r"(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
                 pythonfile_xml = cre.sub(repl, pythonfile_xml)
 
             try:
@@ -74,7 +75,7 @@
                     self.CreateCodeFileBuffer(False)
                     self.OnCTNSave()
             except Exception as exc:
-                error = unicode(exc)
+                error = text(exc)
 
             if error is not None:
                 self.GetCTRoot().logger.write_error(
@@ -317,4 +318,4 @@
         return ([(Gen_PyCfile_path, matiec_CFLAGS)],
                 "",
                 True,
-                ("runtime_%s.py" % location_str, file(runtimefile_path, "rb")))
+                ("runtime_%s.py" % location_str, open(runtimefile_path, "rb")))
--- a/runtime/PLCObject.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/runtime/PLCObject.py	Fri Nov 23 12:13:24 2018 +0100
@@ -30,6 +30,10 @@
 import traceback
 from time import time
 import _ctypes  # pylint: disable=wrong-import-order
+from past.builtins import execfile
+import Pyro.core as pyro
+import six
+from six.moves import _thread, xrange
 
 from runtime.typemapping import TypeTranslator
 from runtime.loglevels import LogLevelsDefault, LogLevelsCount
@@ -95,12 +99,12 @@
                 self._GetMD5FileName(),
                 "r").read().strip() + lib_ext
             if self.LoadPLC():
-                self.PLCStatus = "Stopped"
+                self.PLCStatus = PlcStatus.Stopped
                 if autostart:
                     self.StartPLC()
                     return
         except Exception:
-            self.PLCStatus = "Empty"
+            self.PLCStatus = PlcStatus.Empty
             self.CurrentPLCFilename = None
 
         self.StatusChange()
@@ -466,7 +470,7 @@
             try:
                 if replace_PLC_shared_object:
                     os.remove(old_PLC_filename)
-                for filename in file(extra_files_log, "r").readlines() + [extra_files_log]:
+                for filename in open(extra_files_log, "rt").readlines() + [extra_files_log]:
                     try:
                         os.remove(os.path.join(self.workingdir, filename.strip()))
                     except Exception:
@@ -483,7 +487,7 @@
                 open(self._GetMD5FileName(), "w").write(md5sum)
 
                 # Then write the files
-                log = file(extra_files_log, "w")
+                log = open(extra_files_log, "w")
                 for fname, fdata in extrafiles:
                     fpath = os.path.join(self.workingdir, fname)
                     open(fpath, "wb").write(fdata)
--- a/runtime/WampClient.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/runtime/WampClient.py	Fri Nov 23 12:13:24 2018 +0100
@@ -28,6 +28,7 @@
 import json
 import os
 import re
+from builtins import str as text
 from autobahn.twisted import wamp
 from autobahn.twisted.websocket import WampWebSocketClientFactory, connectWS
 from autobahn.wamp import types, auth
--- a/svgui/pyjs/build.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/svgui/pyjs/build.py	Fri Nov 23 12:13:24 2018 +0100
@@ -10,7 +10,7 @@
 from os.path import join, basename, abspath, split, isfile, isdir
 from hashlib import md5
 from optparse import OptionParser
-from cStringIO import StringIO
+from six.moves import cStringIO
 
 from svgui.pyjs import pyjs
 
@@ -45,7 +45,7 @@
 
 
 # .cache.html files produces look like this
-CACHE_HTML_PAT = re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$')
+CACHE_HTML_PAT = re.compile(r'^[a-z]*.[0-9a-f]{32}\.cache\.html$')
 
 # ok these are the three "default" library directories, containing
 # the builtins (str, List, Dict, ord, round, len, range etc.)
@@ -184,7 +184,7 @@
         try:
             print("Creating output directory")
             os.mkdir(output)
-        except StandardError as e:
+        except OSError as e:
             print("Exception creating output directory %s: %s" % (output, e), file=sys.stderr)
 
     # public dir
@@ -254,7 +254,7 @@
 
     # the selector templ is added to the selectScript function
     select_tmpl = """O(["true","%s"],"%s");"""
-    script_selectors = StringIO()
+    script_selectors = cStringIO()
 
     for platform, file_prefix in app_files:
         print(select_tmpl % (platform, file_prefix), file=script_selectors)
@@ -453,7 +453,7 @@
             if dynamic:
                 mod_cache_html_output = open(join(output, mod_cache_name), "w")
             else:
-                mod_cache_html_output = StringIO()
+                mod_cache_html_output = cStringIO()
 
             print(mod_cache_html_template % dict(
                 mod_name=mod_name,
--- a/svgui/pyjs/jsonrpc/django/jsonrpc.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/svgui/pyjs/jsonrpc/django/jsonrpc.py	Fri Nov 23 12:13:24 2018 +0100
@@ -4,6 +4,7 @@
 
 from __future__ import absolute_import
 import datetime
+from builtins import str as text
 
 from django.core.serializers import serialize
 
@@ -74,7 +75,7 @@
         if error not in d:
             d[error] = []
         for errorval in form.errors[error]:
-            d[error].append(unicode(errorval))
+            d[error].append(text(errorval))
     return d
 
 
@@ -101,7 +102,7 @@
     field_type = field.__class__.__name__
     msgs = {}
     for n, m in field.error_messages.items():
-        msgs[n] = unicode(m)
+        msgs[n] = text(m)
     res['error_messages'] = msgs
     if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
         res['fields'] = map(describe_field, field.fields)
--- a/svgui/pyjs/lib/pyjslib.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/svgui/pyjs/lib/pyjslib.py	Fri Nov 23 12:13:24 2018 +0100
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# pylint: disable=too-many-function-args,undefined-variable,no-absolute-import,assign-to-new-keyword
+# pylint: disable=too-many-function-args,undefined-variable,no-absolute-import,assign-to-new-keyword,nonzero-method,next-method-called,next-method-defined
 
 # iteration from Bob Ippolito's Iteration in JavaScript
 
@@ -285,7 +285,7 @@
         return "AttributeError: %s of %s" % (self.args[1], self.args[0])
 
 
-JS("""
+JS(r"""
 pyjslib.StopIteration = function () { };
 pyjslib.StopIteration.prototype = new Error();
 pyjslib.StopIteration.name = 'StopIteration';
--- a/svgui/pyjs/pyjs.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/svgui/pyjs/pyjs.py	Fri Nov 23 12:13:24 2018 +0100
@@ -13,16 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# pylint: disable=no-absolute-import
+# pylint: disable=no-absolute-import,bad-python3-import
 
 from __future__ import print_function
 import sys
-from types import StringType
 import compiler
 from compiler import ast
 import os
 import copy
-import cStringIO
+from builtins import str as text
+from past.builtins import basestring
+from six.moves import cStringIO
 
 # the standard location for builtins (e.g. pyjslib) can be
 # over-ridden by changing this.  it defaults to sys.prefix
@@ -1359,7 +1360,7 @@
             return str(node.value)
         elif isinstance(node.value, basestring):
             v = node.value
-            if isinstance(node.value, unicode):
+            if isinstance(node.value, text):
                 v = v.encode('utf-8')
             return "String('%s')" % escapejs(v)
         elif node.value is None:
@@ -1386,7 +1387,7 @@
         return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass)
 
     def _mod(self, node, current_klass):
-        if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType):
+        if isinstance(node.left, ast.Const) and isinstance(node.left.value, str):
             self.imported_js.add("sprintf.js")  # Include the sprintf functionality if it is used
             return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")"
         return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass)
@@ -1443,7 +1444,7 @@
             raise TranslationError("varargs are not supported in Lambdas", node)
         if node.kwargs:
             raise TranslationError("kwargs are not supported in Lambdas", node)
-        res = cStringIO.StringIO()
+        res = cStringIO()
         arg_names = list(node.argnames)
         function_args = ", ".join(arg_names)
         for child in node.getChildNodes():
@@ -1531,10 +1532,10 @@
 
 
 def translate(file_name, module_name, debug=False):
-    f = file(file_name, "r")
+    f = open(file_name, "r")
     src = f.read()
     f.close()
-    output = cStringIO.StringIO()
+    output = cStringIO()
     mod = compiler.parseFile(file_name)
     Translator(module_name, module_name, module_name, src, debug, mod, output)
     return output.getvalue()
@@ -1683,9 +1684,9 @@
 
         file_name = self.findFile(module_name + self.extension)
 
-        output = cStringIO.StringIO()
-
-        f = file(file_name, "r")
+        output = cStringIO()
+
+        f = open(file_name, "r")
         src = f.read()
         f.close()
 
@@ -1718,8 +1719,8 @@
 
     def translate(self, module_name, is_app=True, debug=False,
                   library_modules=None):
-        app_code = cStringIO.StringIO()
-        lib_code = cStringIO.StringIO()
+        app_code = cStringIO()
+        lib_code = cStringIO()
         imported_js = set()
         self.library_modules = []
         self.overrides = {}
@@ -1748,7 +1749,7 @@
                 if self.verbose:
                     print('Including JS', js)
                 print('\n//\n// BEGIN JS '+js+'\n//\n', file=lib_code)
-                print(file(path).read(), file=lib_code)
+                print(open(path).read(), file=lib_code)
                 print('\n//\n// END JS '+js+'\n//\n', file=lib_code)
             else:
                 print('Warning: Unable to find imported javascript:', js, file=sys.stderr)
--- a/svgui/svgui.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/svgui/svgui.py	Fri Nov 23 12:13:24 2018 +0100
@@ -93,7 +93,7 @@
 
         svgfile = self._getSVGpath()
         if os.path.exists(svgfile):
-            res += (("gui.svg", file(svgfile, "rb")),)
+            res += (("gui.svg", open(svgfile, "rb")),)
 
         svguiserverfile = open(self._getSVGUIserverpath(), 'r')
         svguiservercode = svguiserverfile.read()
@@ -111,7 +111,7 @@
         svguilibfile.write(open(os.path.join(fpath, "livesvg.js"), 'r').read())
         svguilibfile.close()
         jsmodules = {"LiveSVGPage": "svguilib.js"}
-        res += (("svguilib.js", file(svguilibpath, "rb")),)
+        res += (("svguilib.js", open(svguilibpath, "rb")),)
 
         runtimefile_path = os.path.join(buildpath, "runtime_%s.py" % location_str)
         runtimefile = open(runtimefile_path, 'w')
@@ -128,7 +128,7 @@
                "jsmodules": str(jsmodules)})
         runtimefile.close()
 
-        res += (("runtime_%s.py" % location_str, file(runtimefile_path, "rb")),)
+        res += (("runtime_%s.py" % location_str, open(runtimefile_path, "rb")),)
 
         return res
 
--- a/svgui/svgui_server.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/svgui/svgui_server.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,6 +25,7 @@
 
 from __future__ import absolute_import
 import os
+from builtins import str as text
 
 from nevow import tags, loaders
 import simplejson as json  # pylint: disable=import-error
@@ -122,13 +123,13 @@
     def HMIinitialisation(self):
         gadgets = []
         for gadget in svguiWidgets.values():
-            gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
+            gadgets.append(text(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
         d = self.callRemote('init', gadgets)
         d.addCallback(self.HMIinitialised)
 
     def sendData(self, data):
         if self.initialised:
-            return self.callRemote('receiveData', unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
+            return self.callRemote('receiveData', text(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
         return None
 
     def setattr(self, id, attrname, value):
@@ -139,7 +140,7 @@
     id = getNewId()
     gad = SvguiWidget(args[0], id, **kwargs)
     svguiWidgets[id] = gad
-    gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
+    gadget = [text(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
     interface = website.getHMI()
     if isinstance(interface, SVGUI_HMI) and interface.initialised:
         interface.callRemote('init', gadget)
--- a/targets/toolchain_gcc.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/targets/toolchain_gcc.py	Fri Nov 23 12:13:24 2018 +0100
@@ -29,11 +29,11 @@
 import re
 import operator
 import hashlib
-
+from functools import reduce
 from util.ProcessLogger import ProcessLogger
 
 
-includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*')
+includes_re = re.compile(r'\s*#include\s*["<]([^">]*)[">].*')
 
 
 class toolchain_gcc(object):
--- a/targets/toolchain_makefile.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/targets/toolchain_makefile.py	Fri Nov 23 12:13:24 2018 +0100
@@ -28,11 +28,11 @@
 import re
 import operator
 import hashlib
-
+from functools import reduce
 from util.ProcessLogger import ProcessLogger
 
 
-includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*')
+includes_re = re.compile(r'\s*#include\s*["<]([^">]*)[">].*')
 
 
 class toolchain_makefile(object):
--- a/tests/tools/check_source.sh	Fri Nov 23 11:01:20 2018 +0100
+++ b/tests/tools/check_source.sh	Fri Nov 23 12:13:24 2018 +0100
@@ -31,6 +31,11 @@
     fi
 }
 
+version_gt()
+{
+    test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1";
+}
+
 
 compile_checks()
 {
@@ -115,8 +120,7 @@
     test -z $pep8 && return
 
     user_ignore=
-    # user_ignore=$user_ignore,E265  # E265 block comment should start with '# '
-    user_ignore=$user_ignore,E501  # E501 line too long (80 > 79 characters)
+    user_ignore=$user_ignore,W606  # W606 'async' and 'await' are reserved keywords starting with Python 3.7
 
     # ignored by default,
     default_ignore=
@@ -129,10 +133,11 @@
     default_ignore=$default_ignore,E242  # E242 tab after ‘,’
     default_ignore=$default_ignore,E704  # E704 multiple statements on one line (def)
     default_ignore=$default_ignore,W503  # W503 line break occurred before a binary operator
+    default_ignore=$default_ignore,W504  # W504 line break occurred after a binary operator
+    default_ignore=$default_ignore,W505  # W505 doc line too long (82 > 79 characters)
     ignore=$user_ignore,$default_ignore
 
-    # $pep8 --ignore $ignore --exclude build ./
-    $pep8 --max-line-length 300 --exclude build $py_files
+    $pep8 --max-line-length 300 --ignore=$ignore --exclude build $py_files
     if [ $? -ne 0 ]; then
         set_exit_error
     fi
@@ -237,6 +242,7 @@
 }
 
 pylint_checks()
+
 {
     echo "Check for problems using pylint ..."
 
@@ -256,7 +262,6 @@
     disable=$disable,C0103        # invalid-name
     disable=$disable,C0326        # bad whitespace
     disable=$disable,W0110        # (deprecated-lambda) map/filter on lambda could be replaced by comprehension
-    disable=$disable,W1401        # (anomalous-backslash-in-string) Anomalous backslash in string: '\.'. String constant might be missing an r prefix.
     disable=$disable,W0613        # (unused-argument) Unused argument 'X'
     disable=$disable,W0622        # (redefined-builtin) Redefining built-in
     disable=$disable,W0621        # (redefined-outer-name) Redefining name 'Y' from outer scope (line X)
@@ -347,9 +352,39 @@
     enable=$enable,W0612          # (unused-variable) Unused variable 'X'
     enable=$enable,C0330          # (bad-continuation) Wrong hanging indentation before block
     enable=$enable,R0123          # (literal-comparison) Comparison to literal
+
+    # python3 compatibility checks
+    enable=$enable,W1648          # (bad-python3-import) Module moved in Python 3
+    enable=$enable,W1613          # (xrange-builtin) xrange built-in referenced
+    enable=$enable,W1612          # (unicode-builtin) unicode built-in referenced
+    enable=$enable,W1619          # (old-division) division w/o __future__ statement
+    enable=$enable,W1601          # (apply-builtin) apply built-in referenced
+    enable=$enable,W1659          # (xreadlines-attribute) Accessing a removed xreadlines attribute
+    enable=$enable,W1607          # (file-builtin) file built-in referenced
+    enable=$enable,W1606          # (execfile-builtin) execfile built-in referenced
+    enable=$enable,W1629          # (nonzero-method) __nonzero__ method defined
+    enable=$enable,W1602          # (basestring-builtin) basestring built-in referenced
+    enable=$enable,W1646          # (invalid-str-codec) non-text encoding used in str.decode
+    enable=$enable,W1645          # (exception-message-attribute) Exception.message removed in Python 3
+    enable=$enable,W1649          # (deprecated-string-function) Accessing a deprecated function on the string module
+    enable=$enable,W1651          # (deprecated-itertools-function) Accessing a deprecated function on the itertools module
+    enable=$enable,W1652          # (deprecated-types-field) Accessing a deprecated fields on the types module
+    enable=$enable,W1611          # (standarderror-builtin) StandardError built-in referenced
+    enable=$enable,W1624          # (indexing-exception) Indexing exceptions will not work on Python 3
+    enable=$enable,W1625          # (raising-string) Raising a string exception
+    enable=$enable,W1622          # (next-method-called) Called a next() method on an object
+    enable=$enable,W1653          # (next-method-defined) next method defined
+    enable=$enable,W1610          # (reduce-builtin) reduce built-in referenced
+    enable=$enable,W1633          # (round-builtin) round built-in referenced
     # enable=
 
     options=
+
+    ver=$(pylint --version 2>&1 | grep pylint  | awk '{ print $2 }')
+    if version_gt $ver '1.6.8'; then
+	echo "Use multiple threads for pylint"
+	options="$options --jobs=0 "
+    fi
     options="$options --rcfile=.pylint"
     # options="$options --py3k"   # report errors for Python 3 porting
 
--- a/tests/tools/run_python_tests.sh	Fri Nov 23 11:01:20 2018 +0100
+++ b/tests/tools/run_python_tests.sh	Fri Nov 23 12:13:24 2018 +0100
@@ -1,17 +1,61 @@
 #!/bin/sh
 
-LC_ALL=ru_RU.utf-8
 
-export DISPLAY=:42
-Xvfb $DISPLAY -screen 0 1280x1024x24 &
-sleep 1
 
-ret=0
-DELAY=400
-KILL_DELAY=$(($DELAY + 30))
-timeout -k $KILL_DELAY $DELAY pytest --timeout=10 ./tests/tools
-ret=$?
+cleanup()
+{
+    find $PYTEST_DIR -name '*.pyc' -delete
+}
 
-pkill -9 Xvfb
 
-exit $ret
+
+print_help()
+{
+    echo "Usage: run_python_tests.sh [--on-local-xserver]"
+    echo ""
+    echo "--on-local-xserver"
+    echo "                all tests are run on local X-server. "
+    echo "                User can see test in action."
+    echo "                Any interaction (mouse, keyboard) should be avoided"
+    echo "                By default without arguments script runs pytest on virtual X serverf."
+    echo ""
+
+    exit 1
+}
+
+main()
+{
+    LC_ALL=ru_RU.utf-8
+    PYTEST_DIR=./tests/tools
+
+    if [ ! -d $PYTEST_DIR ]; then
+	echo "Script should be run from top directory in repository"
+	exit 1;
+    fi
+
+    use_xvfb=0
+    if [ "$1" != "--on-local-xserver" ]; then
+	export DISPLAY=:42
+	use_xvfb=1
+	Xvfb $DISPLAY -screen 0 1280x1024x24 &
+	sleep 1
+    fi
+
+
+    cleanup
+
+    ret=0
+    DELAY=400
+    KILL_DELAY=$(($DELAY + 30))
+    timeout -k $KILL_DELAY $DELAY pytest --timeout=10 ./tests/tools
+    ret=$?
+
+    cleanup
+
+    [ $use_xvfb = 1 ] && pkill -9 Xvfb
+    exit $ret
+}
+
+
+[ "$1" = "--help" -o "$1" = "-h" ] && print_help
+main $@
--- a/tests/tools/test_CustomIntCtrl.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/tests/tools/test_CustomIntCtrl.py	Fri Nov 23 12:13:24 2018 +0100
@@ -24,6 +24,7 @@
 
 
 from __future__ import absolute_import
+from __future__ import division
 import unittest
 import time
 
@@ -66,7 +67,7 @@
     def testCorrectValue(self):
         """Test case if no limiting is necessary"""
         self.AddControls()
-        val = (self.max_val + self.min_val) / 2
+        val = (self.max_val + self.min_val) // 2
         self.int_ctrl.SetValue(val)
         self.ProcessEvents()
 
@@ -86,7 +87,7 @@
 
         self.int_ctrl.Bind(controls.CustomIntCtrl.EVT_CUSTOM_INT, EventHandler)
 
-        val = (self.max_val + self.min_val) / 2
+        val = (self.max_val + self.min_val) // 2
 
         self.int_ctrl.SetValue(val)
         self.ProcessEvents()
--- a/util/TranslationCatalogs.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/util/TranslationCatalogs.py	Fri Nov 23 12:13:24 2018 +0100
@@ -25,14 +25,14 @@
 
 from __future__ import absolute_import
 import os
-import __builtin__
+from six.moves import builtins
 import wx
 
 
 locale = None
 
 
-__builtin__.__dict__['_'] = wx.GetTranslation
+builtins.__dict__['_'] = wx.GetTranslation
 
 
 def GetDomain(path):
--- a/util/misc.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/util/misc.py	Fri Nov 23 12:13:24 2018 +0100
@@ -29,6 +29,7 @@
 
 from __future__ import absolute_import
 import os
+from functools import reduce
 
 from util.BitmapLibrary import AddBitmapFolder
 from util.TranslationCatalogs import AddCatalog
--- a/util/paths.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/util/paths.py	Fri Nov 23 12:13:24 2018 +0100
@@ -26,11 +26,12 @@
 from __future__ import absolute_import
 import os
 import sys
+from builtins import str as text
 
 
 def AbsFile(file):
     if isinstance(file, str):
-        file = unicode(file, sys.getfilesystemencoding())
+        file = text(file, sys.getfilesystemencoding())
     return file
 
 
--- a/xmlclass/xmlclass.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/xmlclass/xmlclass.py	Fri Nov 23 12:13:24 2018 +0100
@@ -28,12 +28,14 @@
 import os
 import re
 import datetime
-from types import *
 from xml.dom import minidom
 from xml.sax.saxutils import unescape
-from new import classobj
 from collections import OrderedDict
-
+from builtins import str as text
+from functools import reduce
+
+from six import string_types
+from six.moves import xrange
 from lxml import etree
 
 
@@ -51,33 +53,33 @@
 
 def NodeSetAttr(node, name, value):
     attr = minidom.Attr(name)
-    text = minidom.Text()
-    text.data = value
-    attr.childNodes[0] = text
+    txt = minidom.Text()
+    txt.data = value
+    attr.childNodes[0] = txt
     node._attrs[name] = attr
 
 
 # Regular expression models for checking all kind of
 # string values defined in XML standard
 
-Name_model = re.compile('([a-zA-Z_\:][\w\.\-\:]*)$')
-Names_model = re.compile('([a-zA-Z_\:][\w\.\-\:]*(?: [a-zA-Z_\:][\w\.\-\:]*)*)$')
-NMToken_model = re.compile('([\w\.\-\:]*)$')
-NMTokens_model = re.compile('([\w\.\-\:]*(?: [\w\.\-\:]*)*)$')
-QName_model = re.compile('((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)$')
-QNames_model = re.compile('((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*(?: (?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)*)$')
-NCName_model = re.compile('([a-zA-Z_][\w]*)$')
-URI_model = re.compile('((?:htt(p|ps)://|/)?(?:[\w.-]*/?)*)$')
-LANGUAGE_model = re.compile('([a-zA-Z]{1,8}(?:-[a-zA-Z0-9]{1,8})*)$')
-
-ONLY_ANNOTATION = re.compile("((?:annotation )?)")
+Name_model = re.compile(r'([a-zA-Z_\:][\w\.\-\:]*)$')
+Names_model = re.compile(r'([a-zA-Z_\:][\w\.\-\:]*(?: [a-zA-Z_\:][\w\.\-\:]*)*)$')
+NMToken_model = re.compile(r'([\w\.\-\:]*)$')
+NMTokens_model = re.compile(r'([\w\.\-\:]*(?: [\w\.\-\:]*)*)$')
+QName_model = re.compile(r'((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)$')
+QNames_model = re.compile(r'((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*(?: (?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)*)$')
+NCName_model = re.compile(r'([a-zA-Z_][\w]*)$')
+URI_model = re.compile(r'((?:htt(p|ps)://|/)?(?:[\w.-]*/?)*)$')
+LANGUAGE_model = re.compile(r'([a-zA-Z]{1,8}(?:-[a-zA-Z0-9]{1,8})*)$')
+
+ONLY_ANNOTATION = re.compile(r"((?:annotation )?)")
 
 """
 Regular expression models for extracting dates and times from a string
 """
-time_model = re.compile('([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)(?:Z)?$')
-date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
-datetime_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
+time_model = re.compile(r'([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)(?:Z)?$')
+date_model = re.compile(r'([0-9]{4})-([0-9]{2})-([0-9]{2})((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
+datetime_model = re.compile(r'([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
 
 
 class xml_timezone(datetime.tzinfo):
@@ -139,13 +141,13 @@
     if not extract:
         return attr
     if len(attr.childNodes) == 1:
-        return unicode(unescape(attr.childNodes[0].data))
+        return text(unescape(attr.childNodes[0].data))
     else:
         # content is a CDATA
-        text = u''
+        txt = u''
         for node in attr.childNodes:
             if not (node.nodeName == "#text" and node.data.strip() == u''):
-                text += unicode(unescape(node.data))
+                txt += text(unescape(node.data))
         return text
 
 
@@ -574,7 +576,7 @@
         "extract": ExtractAny,
         "generate": GenerateAny,
         "initial": InitialAny,
-        "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase))
+        "check": lambda x: isinstance(x, (string_types, etree.ElementBase))
     }
 
 
@@ -606,7 +608,7 @@
 
 
 def FindTypeInfos(factory, infos):
-    if isinstance(infos, (UnicodeType, StringType)):
+    if isinstance(infos, string_types):
         namespace, name = DecomposeQualifiedName(infos)
         return factory.GetQualifiedNameInfos(name, namespace)
     return infos
@@ -952,7 +954,7 @@
                   if parent is not None else None)
         parent_class = lookup_classes.get(parent)
         if parent_class is not None:
-            if isinstance(parent_class, ListType):
+            if isinstance(parent_class, list):
                 if typeinfos not in parent_class:
                     lookup_classes[parent].append(typeinfos)
             elif parent_class != typeinfos:
@@ -962,13 +964,13 @@
 
     def AddToLookupClass(self, name, parent, typeinfos):
         lookup_name = self.etreeNamespaceFormat % name
-        if isinstance(typeinfos, (StringType, UnicodeType)):
+        if isinstance(typeinfos, string_types):
             self.AddEquivalentClass(name, typeinfos)
             typeinfos = self.etreeNamespaceFormat % typeinfos
         lookup_classes = self.ComputedClassesLookUp.get(lookup_name)
         if lookup_classes is None:
             self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent)
-        elif isinstance(lookup_classes, DictType):
+        elif isinstance(lookup_classes, dict):
             self.AddDistinctionBetweenParentsInLookupClass(
                 lookup_classes, parent, typeinfos)
         else:
@@ -980,7 +982,7 @@
             self.ComputedClassesLookUp[lookup_name] = lookup_classes
 
     def ExtractTypeInfos(self, name, parent, typeinfos):
-        if isinstance(typeinfos, (StringType, UnicodeType)):
+        if isinstance(typeinfos, string_types):
             namespace, type_name = DecomposeQualifiedName(typeinfos)
             infos = self.GetQualifiedNameInfos(type_name, namespace)
             if name != "base":
@@ -991,13 +993,13 @@
             if infos["type"] == COMPLEXTYPE:
                 type_name, parent = self.SplitQualifiedName(type_name, namespace)
                 result = self.CreateClass(type_name, parent, infos)
-                if result is not None and not isinstance(result, (UnicodeType, StringType)):
+                if result is not None and not isinstance(result, string_types):
                     self.Namespaces[self.TargetNamespace][result["name"]] = result
                 return result
             elif infos["type"] == ELEMENT and infos["elmt_type"]["type"] == COMPLEXTYPE:
                 type_name, parent = self.SplitQualifiedName(type_name, namespace)
                 result = self.CreateClass(type_name, parent, infos["elmt_type"])
-                if result is not None and not isinstance(result, (UnicodeType, StringType)):
+                if result is not None and not isinstance(result, string_types):
                     self.Namespaces[self.TargetNamespace][result["name"]] = result
                 return result
             else:
@@ -1019,19 +1021,19 @@
         self.ParseSchema()
         for name, infos in self.Namespaces[self.TargetNamespace].items():
             if infos["type"] == ELEMENT:
-                if not isinstance(infos["elmt_type"], (UnicodeType, StringType)) and \
+                if not isinstance(infos["elmt_type"], string_types) and \
                    infos["elmt_type"]["type"] == COMPLEXTYPE:
                     self.ComputeAfter.append((name, None, infos["elmt_type"], True))
                     while len(self.ComputeAfter) > 0:
                         result = self.CreateClass(*self.ComputeAfter.pop(0))
-                        if result is not None and not isinstance(result, (UnicodeType, StringType)):
+                        if result is not None and not isinstance(result, string_types):
                             self.Namespaces[self.TargetNamespace][result["name"]] = result
             elif infos["type"] == COMPLEXTYPE:
                 self.ComputeAfter.append((name, None, infos))
                 while len(self.ComputeAfter) > 0:
                     result = self.CreateClass(*self.ComputeAfter.pop(0))
                     if result is not None and \
-                       not isinstance(result, (UnicodeType, StringType)):
+                       not isinstance(result, string_types):
                         self.Namespaces[self.TargetNamespace][result["name"]] = result
             elif infos["type"] == ELEMENTSGROUP:
                 elements = []
@@ -1040,17 +1042,17 @@
                 elif "choices" in infos:
                     elements = infos["choices"]
                 for element in elements:
-                    if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and \
+                    if not isinstance(element["elmt_type"], string_types) and \
                        element["elmt_type"]["type"] == COMPLEXTYPE:
                         self.ComputeAfter.append((element["name"], infos["name"], element["elmt_type"]))
                         while len(self.ComputeAfter) > 0:
                             result = self.CreateClass(*self.ComputeAfter.pop(0))
                             if result is not None and \
-                               not isinstance(result, (UnicodeType, StringType)):
+                               not isinstance(result, string_types):
                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
 
         for name, parents in self.ComputedClassesLookUp.iteritems():
-            if isinstance(parents, DictType):
+            if isinstance(parents, dict):
                 computed_classes = parents.items()
             elif parents[1] is not None:
                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
@@ -1058,7 +1060,7 @@
                 computed_classes = []
             for parent, computed_class in computed_classes:
                 for equivalent_parent in self.GetEquivalentParents(parent):
-                    if not isinstance(parents, DictType):
+                    if not isinstance(parents, dict):
                         parents = dict(computed_classes)
                         self.ComputedClassesLookUp[name] = parents
                     parents[equivalent_parent] = computed_class
@@ -1168,7 +1170,7 @@
         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
 
-        class_definition = classobj(str(name), bases, classmembers)
+        class_definition = type(str(name), bases, classmembers)
         setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
         setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
         class_infos = {
@@ -1248,7 +1250,7 @@
         if element["type"] == ANY:
             infos = element.copy()
             infos["minOccurs"] = 0
-            elements.append(ComputeMultiplicity("#text |#cdata-section |\w* ", infos))
+            elements.append(ComputeMultiplicity(r"#text |#cdata-section |\w* ", infos))
         elif element["type"] == CHOICE:
             choices = []
             for infos in element["choices"]:
@@ -1381,7 +1383,7 @@
                     else:
                         insertion_point = 0
 
-                    if not isinstance(value, ListType):
+                    if not isinstance(value, list):
                         value = [value]
 
                     for element in reversed(value):
@@ -1720,7 +1722,7 @@
     return countMethod
 
 
-NAMESPACE_PATTERN = re.compile("xmlns(?:\:[^\=]*)?=\"[^\"]*\" ")
+NAMESPACE_PATTERN = re.compile(r"xmlns(?:\:[^\=]*)?=\"[^\"]*\" ")
 
 
 class DefaultElementClass(etree.ElementBase):
@@ -1747,13 +1749,13 @@
 
     def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
         element_class = self.LookUpClasses.get(element_tag, (default, None))
-        if not isinstance(element_class, DictType):
-            if isinstance(element_class[0], (StringType, UnicodeType)):
+        if not isinstance(element_class, dict):
+            if isinstance(element_class[0], string_types):
                 return self.GetElementClass(element_class[0], default=default)
             return element_class[0]
 
         element_with_parent_class = element_class.get(parent_tag, default)
-        if isinstance(element_with_parent_class, (StringType, UnicodeType)):
+        if isinstance(element_with_parent_class, string_types):
             return self.GetElementClass(element_with_parent_class, default=default)
         return element_with_parent_class
 
@@ -1810,12 +1812,12 @@
         parent = element.getparent()
         element_class = self.GetElementClass(
             element.tag, parent.tag if parent is not None else None)
-        if isinstance(element_class, ListType):
+        if isinstance(element_class, list):
             children = "".join([
                 "%s " % etree.QName(child.tag).localname
                 for child in element])
             for possible_class in element_class:
-                if isinstance(possible_class, (StringType, UnicodeType)):
+                if isinstance(possible_class, string_types):
                     possible_class = self.GetElementClass(possible_class)
                 if possible_class.StructurePattern.match(children) is not None:
                     return possible_class
@@ -1889,7 +1891,7 @@
             (subclass of lxml.etree._Element created by class factory)
         """
         element_class = self.GetElementClass(element_tag, parent_tag)
-        if isinstance(element_class, ListType):
+        if isinstance(element_class, list):
             if class_idx is not None and class_idx < len(element_class):
                 element_class = element_class[class_idx]
             else:
--- a/xmlclass/xsdschema.py	Fri Nov 23 11:01:20 2018 +0100
+++ b/xmlclass/xsdschema.py	Fri Nov 23 12:13:24 2018 +0100
@@ -28,8 +28,11 @@
 import os
 import re
 import datetime
+from types import FunctionType
 from xml.dom import minidom
-from types import *
+from future.builtins import round
+from six import string_types
+from past.builtins import long
 
 from xmlclass.xmlclass import *
 
@@ -61,7 +64,7 @@
         if name is not None:
             ind1, _ind2 = getIndent(indent, name)
             text += ind1 + "<%s>" % name
-        if isinstance(value, IntType):
+        if isinstance(value, int):
             text += str(value)
         elif value in extra_values or value % 1 != 0:
             text += float_format(value)
@@ -167,7 +170,7 @@
 
     if typeinfos["type"] in ["restriction", "extension"]:
         # Search for base type definition
-        if isinstance(typeinfos["base"], (StringType, UnicodeType)):
+        if isinstance(typeinfos["base"], string_types):
             basetypeinfos = factory.FindSchemaElement(typeinfos["base"], SIMPLETYPE)
             if basetypeinfos is None:
                 raise "\"%s\" isn't defined!" % typeinfos["base"]
@@ -391,7 +394,7 @@
 
     elif typeinfos["type"] == "list":
         # Search for item type definition
-        if isinstance(typeinfos["itemType"], (StringType, UnicodeType)):
+        if isinstance(typeinfos["itemType"], string_types):
             itemtypeinfos = factory.FindSchemaElement(typeinfos["itemType"], SIMPLETYPE)
             if itemtypeinfos is None:
                 raise "\"%s\" isn't defined!" % typeinfos["itemType"]
@@ -437,7 +440,7 @@
         # Search for member types definition
         membertypesinfos = []
         for membertype in typeinfos["memberTypes"]:
-            if isinstance(membertype, (StringType, UnicodeType)):
+            if isinstance(membertype, string_types):
                 infos = factory.FindSchemaElement(membertype, SIMPLETYPE)
                 if infos is None:
                     raise ValueError("\"%s\" isn't defined!" % membertype)
@@ -478,7 +481,7 @@
         SimpleTypeInitialValue = membertypesinfos[0]["initial"]
 
         def GenerateSimpleTypeFunction(value):
-            if isinstance(value, BooleanType):
+            if isinstance(value, bool):
                 return {True: "true", False: "false"}[value]
             else:
                 return str(value)
@@ -511,7 +514,7 @@
     attrnames = {}
     if base is not None:
         basetypeinfos = factory.FindSchemaElement(base)
-        if not isinstance(basetypeinfos, (UnicodeType, StringType)) and basetypeinfos["type"] == COMPLEXTYPE:
+        if not isinstance(basetypeinfos, string_types) and basetypeinfos["type"] == COMPLEXTYPE:
             attrnames = dict(map(lambda x: (x["name"], True), basetypeinfos["attributes"]))
 
     for element in elements:
@@ -812,7 +815,7 @@
                 raise ValueError("Only group composed of \"choice\" can be referenced in \"choice\" element!")
             choices_tmp = []
             for choice in elmtgroup["choices"]:
-                if not isinstance(choice["elmt_type"], (UnicodeType, StringType)) and choice["elmt_type"]["type"] == COMPLEXTYPE:
+                if not isinstance(choice["elmt_type"], string_types) and choice["elmt_type"]["type"] == COMPLEXTYPE:
                     elmt_type = "%s_%s" % (elmtgroup["name"], choice["name"])
                     if factory.TargetNamespace is not None:
                         elmt_type = "%s:%s" % (factory.TargetNamespace, elmt_type)
@@ -846,7 +849,7 @@
                 raise ValueError("Only group composed of \"sequence\" can be referenced in \"sequence\" element!")
             elements_tmp = []
             for element in elmtgroup["elements"]:
-                if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and element["elmt_type"]["type"] == COMPLEXTYPE:
+                if not isinstance(element["elmt_type"], string_types) and element["elmt_type"]["type"] == COMPLEXTYPE:
                     elmt_type = "%s_%s" % (elmtgroup["name"], element["name"])
                     if factory.TargetNamespace is not None:
                         elmt_type = "%s:%s" % (factory.TargetNamespace, elmt_type)
@@ -982,16 +985,16 @@
 
 
 def CompareSchema(schema, reference):
-    if isinstance(schema, ListType):
-        if not isinstance(reference, ListType) or len(schema) != len(reference):
+    if isinstance(schema, list):
+        if not isinstance(reference, list) or len(schema) != len(reference):
             return False
         for i, value in enumerate(schema):
             result = CompareSchema(value, reference[i])
             if not result:
                 return result
         return True
-    elif isinstance(schema, DictType):
-        if not isinstance(reference, DictType) or len(schema) != len(reference):
+    elif isinstance(schema, dict):
+        if not isinstance(reference, dict) or len(schema) != len(reference):
             return False
         for name, value in schema.items():
             ref_value = reference.get(name, None)
@@ -2212,8 +2215,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
-    },
+        "check": lambda x: isinstance(x, string_types)},
 
     "normalizedString": {
         "type": SIMPLETYPE,
@@ -2222,7 +2224,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "token": {
@@ -2232,7 +2234,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "base64Binary": {
@@ -2242,7 +2244,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, (IntType, LongType))
+        "check": lambda x: isinstance(x, (int, long))
     },
 
     "hexBinary": {
@@ -2252,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, (IntType, LongType))
+        "check": lambda x: isinstance(x, (int, long))
     },
 
     "integer": {
@@ -2262,7 +2264,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "positiveInteger": {
@@ -2272,7 +2274,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 1,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "negativeInteger": {
@@ -2282,7 +2284,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: -1,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "nonNegativeInteger": {
@@ -2292,7 +2294,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "nonPositiveInteger": {
@@ -2302,7 +2304,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "long": {
@@ -2312,7 +2314,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "unsignedLong": {
@@ -2322,7 +2324,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "int": {
@@ -2332,7 +2334,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "unsignedInt": {
@@ -2342,7 +2344,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "short": {
@@ -2352,7 +2354,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "unsignedShort": {
@@ -2362,7 +2364,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "byte": {
@@ -2372,7 +2374,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "unsignedByte": {
@@ -2382,7 +2384,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: 0,
-        "check": lambda x: isinstance(x, IntType)
+        "check": lambda x: isinstance(x, int)
     },
 
     "decimal": {
@@ -2392,7 +2394,7 @@
         "facets": DECIMAL_FACETS,
         "generate": GenerateFloatXMLText(decimal=3),
         "initial": lambda: 0.,
-        "check": lambda x: isinstance(x, (IntType, FloatType))
+        "check": lambda x: isinstance(x, (int, float))
     },
 
     "float": {
@@ -2402,7 +2404,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateFloatXMLText(["INF", "-INF", "NaN"]),
         "initial": lambda: 0.,
-        "check": lambda x: {"INF": True, "-INF": True, "NaN": True}.get(x, isinstance(x, (IntType, FloatType)))
+        "check": lambda x: {"INF": True, "-INF": True, "NaN": True}.get(x, isinstance(x, (int, float)))
     },
 
     "double": {
@@ -2412,7 +2414,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateFloatXMLText(["INF", "-INF", "NaN"]),
         "initial": lambda: 0.,
-        "check": lambda x: {"INF": True, "-INF": True, "NaN": True}.get(x, isinstance(x, (IntType, FloatType)))
+        "check": lambda x: {"INF": True, "-INF": True, "NaN": True}.get(x, isinstance(x, (int, float)))
     },
 
     "boolean": {
@@ -2422,7 +2424,7 @@
         "facets": GenerateDictFacets(["pattern", "whiteSpace"]),
         "generate": GenerateSimpleTypeXMLText(lambda x: {True: "true", False: "false"}[x]),
         "initial": lambda: False,
-        "check": lambda x: isinstance(x, BooleanType)
+        "check": lambda x: isinstance(x, bool)
     },
 
     "duration": {
@@ -2432,7 +2434,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "dateTime": {
@@ -2472,7 +2474,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "gYearMonth": {
@@ -2482,7 +2484,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "gMonth": {
@@ -2492,7 +2494,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "gMonthDay": {
@@ -2502,7 +2504,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "gDay": {
@@ -2512,7 +2514,7 @@
         "facets": NUMBER_FACETS,
         "generate": GenerateSimpleTypeXMLText(str),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "Name": {
@@ -2522,7 +2524,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "QName": {
@@ -2532,7 +2534,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "NCName": {
@@ -2542,7 +2544,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "anyURI": {
@@ -2552,7 +2554,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "language": {
@@ -2562,7 +2564,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "en",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "ID": {
@@ -2572,7 +2574,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "IDREF": {
@@ -2582,7 +2584,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "IDREFS": {
@@ -2592,7 +2594,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "ENTITY": {
@@ -2602,7 +2604,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "ENTITIES": {
@@ -2612,7 +2614,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "NOTATION": {
@@ -2622,7 +2624,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "NMTOKEN": {
@@ -2632,7 +2634,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     "NMTOKENS": {
@@ -2642,7 +2644,7 @@
         "facets": STRING_FACETS,
         "generate": GenerateSimpleTypeXMLText(lambda x: x),
         "initial": lambda: "",
-        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+        "check": lambda x: isinstance(x, string_types)
     },
 
     # Complex Types