# HG changeset patch
# User Edouard Tisserant
# Date 1542971604 -3600
# Node ID 21164625b393cccac287adef8cceb163d8351c01
# Parent  2a70d52403006ad46045aca2b32dc5e1f4bc1b7a# Parent  9deec258ab1ae0c8ceff723d4028f9e9d0de42f0
Merged. Some changes that should already have been incuded during previous merge (mostly about PlcStatus) have been included this time.

diff -r 2a70d5240300 -r 21164625b393 Beremiz.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
diff -r 2a70d5240300 -r 21164625b393 BeremizIDE.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 Beremiz_service.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 CodeFileTreeNode.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 ConfigTreeNode.py
--- 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())
diff -r 2a70d5240300 -r 21164625b393 IDEFrame.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 PLCControler.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 PLCGenerator.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 ProjectController.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 canfestival/canfestival.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 canfestival/config_utils.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 connectors/WAMP/__init__.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 controls/CustomStyledTextCtrl.py
--- 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 = {
diff -r 2a70d5240300 -r 21164625b393 controls/CustomTree.py
--- 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
 
diff -r 2a70d5240300 -r 21164625b393 controls/DebugVariablePanel/DebugVariableGraphicViewer.py
--- 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())
diff -r 2a70d5240300 -r 21164625b393 controls/DebugVariablePanel/DebugVariablePanel.py
--- 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):
diff -r 2a70d5240300 -r 21164625b393 controls/DebugVariablePanel/DebugVariableTextViewer.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 controls/DebugVariablePanel/DebugVariableViewer.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 controls/DiscoveryPanel.py
--- 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.'
 
 
diff -r 2a70d5240300 -r 21164625b393 controls/EnhancedStatusBar.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 controls/FolderTree.py
--- 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
 
diff -r 2a70d5240300 -r 21164625b393 controls/LibraryPanel.py
--- 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
 
 # -------------------------------------------------------------------------------
diff -r 2a70d5240300 -r 21164625b393 controls/LogViewer.py
--- 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):
diff -r 2a70d5240300 -r 21164625b393 controls/PouInstanceVariablesPanel.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 controls/SearchResultPanel.py
--- 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, [])
diff -r 2a70d5240300 -r 21164625b393 controls/TextCtrlAutoComplete.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 controls/VariablePanel.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 dialogs/ArrayTypeDialog.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 dialogs/BlockPreviewDialog.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 dialogs/DurationEditorDialog.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 dialogs/ForceVariableDialog.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 docutil/docpdf.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 docutil/docsvg.py
--- 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('"', '')
 
diff -r 2a70d5240300 -r 21164625b393 editors/CodeFileEditor.py
--- 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):
         """
diff -r 2a70d5240300 -r 21164625b393 editors/ConfTreeNodeEditor.py
--- 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):
diff -r 2a70d5240300 -r 21164625b393 editors/DataTypeEditor.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 editors/LDViewer.py
--- 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])
diff -r 2a70d5240300 -r 21164625b393 editors/ResourceEditor.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 editors/SFCViewer.py
--- 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)])
diff -r 2a70d5240300 -r 21164625b393 editors/TextViewer.py
--- 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()
diff -r 2a70d5240300 -r 21164625b393 editors/Viewer.py
--- 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()
diff -r 2a70d5240300 -r 21164625b393 etherlab/CommonEtherCATFunction.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 etherlab/ConfigEditor.py
--- 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()
diff -r 2a70d5240300 -r 21164625b393 etherlab/EtherCATManagementEditor.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 etherlab/EthercatCFileGenerator.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 etherlab/EthercatMaster.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 etherlab/etherlab.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 graphics/DebugDataConsumer.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 graphics/FBD_Objects.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 graphics/GraphicCommons.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 graphics/LD_Objects.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 graphics/SFC_Objects.py
--- 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):
diff -r 2a70d5240300 -r 21164625b393 i18n/mki18n.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 modbus/mb_utils.py
--- 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
 
diff -r 2a70d5240300 -r 21164625b393 modbus/modbus.py
--- 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
 
diff -r 2a70d5240300 -r 21164625b393 plcopen/plcopen.py
--- 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)
 
 # ----------------------------------------------------------------------
diff -r 2a70d5240300 -r 21164625b393 plcopen/structures.py
--- 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
 
diff -r 2a70d5240300 -r 21164625b393 py_ext/PythonFileCTNMixin.py
--- 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")))
diff -r 2a70d5240300 -r 21164625b393 runtime/PLCObject.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 runtime/WampClient.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 svgui/pyjs/build.py
--- 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,
diff -r 2a70d5240300 -r 21164625b393 svgui/pyjs/jsonrpc/django/jsonrpc.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 svgui/pyjs/lib/pyjslib.py
--- 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';
diff -r 2a70d5240300 -r 21164625b393 svgui/pyjs/pyjs.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 svgui/svgui.py
--- 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
 
diff -r 2a70d5240300 -r 21164625b393 svgui/svgui_server.py
--- 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)
diff -r 2a70d5240300 -r 21164625b393 targets/toolchain_gcc.py
--- 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):
diff -r 2a70d5240300 -r 21164625b393 targets/toolchain_makefile.py
--- 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):
diff -r 2a70d5240300 -r 21164625b393 tests/tools/check_source.sh
--- 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
 
diff -r 2a70d5240300 -r 21164625b393 tests/tools/run_python_tests.sh
--- 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 $@
diff -r 2a70d5240300 -r 21164625b393 tests/tools/test_CustomIntCtrl.py
--- 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()
diff -r 2a70d5240300 -r 21164625b393 util/TranslationCatalogs.py
--- 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):
diff -r 2a70d5240300 -r 21164625b393 util/misc.py
--- 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
diff -r 2a70d5240300 -r 21164625b393 util/paths.py
--- 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
 
 
diff -r 2a70d5240300 -r 21164625b393 xmlclass/xmlclass.py
--- 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:
diff -r 2a70d5240300 -r 21164625b393 xmlclass/xsdschema.py
--- 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