[X2Go-Commits] [python-x2go] 01/10: Port to Python3.

git-admin at x2go.org git-admin at x2go.org
Sun Sep 24 10:51:38 CEST 2017


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch master
in repository python-x2go.

commit 327fa5e5f09d7fabb4d0052de1b2876c852797e1
Author: Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
Date:   Fri Sep 22 13:20:38 2017 +0200

    Port to Python3.
---
 debian/compat                                      |   2 +-
 debian/control                                     |  53 +++++--
 debian/python-x2go-doc.links                       |   1 +
 debian/python-x2go-doc.lintian-overrides           |   2 +-
 debian/python-x2go.install                         |   2 +-
 debian/python3-x2go.docs                           |   3 +
 debian/python3-x2go.examples                       |   1 +
 debian/python3-x2go.install                        |   1 +
 debian/rules                                       |  21 +--
 examples/x2go_resume_session.py                    |   4 +-
 .../x2go_start_session_with_progress_status.py     |   6 +-
 setup.py                                           |   2 +-
 test.py                                            |   2 +-
 x2go/__init__.py                                   |  37 ++---
 x2go/_paramiko.py                                  |   8 +-
 x2go/backends/control/plain.py                     |  70 +++++-----
 x2go/backends/info/plain.py                        |  19 +--
 x2go/backends/printing/file.py                     |  16 +--
 x2go/backends/profiles/base.py                     |  66 ++++-----
 x2go/backends/profiles/file.py                     |   2 +-
 x2go/backends/profiles/httpbroker.py               |  50 +++----
 x2go/backends/proxy/base.py                        |   6 +-
 x2go/backends/proxy/nx3.py                         |   2 +-
 x2go/backends/terminal/plain.py                    |  32 ++---
 x2go/cache.py                                      |  24 ++--
 x2go/checkhosts.py                                 |   8 +-
 x2go/cleanup.py                                    |  10 +-
 x2go/client.py                                     |  64 ++++-----
 x2go/defaults.py                                   |   2 +-
 x2go/forward.py                                    |   6 +-
 x2go/gevent_subprocess.py                          |   9 +-
 x2go/guardian.py                                   |   6 +-
 x2go/inifiles.py                                   |  36 +++--
 x2go/log.py                                        |   8 +-
 x2go/mimebox.py                                    |  16 +--
 x2go/mimeboxactions.py                             |  12 +-
 x2go/printactions.py                               |  22 +--
 x2go/printqueue.py                                 |  16 +--
 x2go/pulseaudio.py                                 |  10 +-
 x2go/registry.py                                   |  60 ++++----
 x2go/rforward.py                                   |  16 ++-
 x2go/session.py                                    | 154 ++++++++++-----------
 x2go/sftpserver.py                                 |  34 ++---
 x2go/sshproxy.py                                   |  36 ++---
 x2go/telekinesis.py                                |  10 +-
 x2go/tests/__init__.py                             |   4 +-
 x2go/tests/test_printing.py                        |  10 +-
 x2go/utils.py                                      |  72 +++++-----
 x2go/x2go_exceptions.py                            |   5 +-
 x2go/xserver.py                                    |  18 +--
 50 files changed, 553 insertions(+), 523 deletions(-)

diff --git a/debian/compat b/debian/compat
index 7f8f011..ec63514 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-7
+9
diff --git a/debian/control b/debian/control
index 1ef957b..529cae2 100644
--- a/debian/control
+++ b/debian/control
@@ -6,20 +6,23 @@ Uploaders:
  Mike Gabriel <mike.gabriel at das-netzwerkteam.de>,
  Mihai Moldovan <ionic at ionic.de>,
 Build-Depends:
- debhelper (>= 7.0.50~),
+ cdbs,
+ debhelper (>= 9~),
 # python (>= 2.6.6-3~),
- python (>= 2.6.5-0~),
- python-setuptools,
+ python3,
+ python3-setuptools,
+ python3-gevent,
+ python3-paramiko,
+ python3-xlib,
  python-epydoc,
- python-gevent,
- python-paramiko,
- python-xlib,
+ dh-python,
  locales
-Standards-Version: 3.9.6
+Standards-Version: 4.1.0
 Homepage: http://code.x2go.org/releases/source/python-x2go
 Vcs-Git: git://code.x2go.org/python-x2go.git
 Vcs-Browser: http://code.x2go.org/gitweb?p=python-x2go.git;a=summary
 X-Python-Version: >= 2.6
+X-Python3-Version: >= 3.4
 
 Package: python-x2go
 Architecture: all
@@ -39,7 +42,39 @@ Recommends:
 Suggests:
  telekinesis-client,
  mteleplayer-clientside,
-Description: Python module providing X2Go client API
+Description: Python module providing X2Go client API (Python 2)
+ X2Go is a server based computing environment with
+    - session resuming
+    - low bandwidth support
+    - session brokerage support
+    - client side mass storage mounting support
+    - client side printing support
+    - audio support
+    - authentication by smartcard and USB stick
+ .
+ This Python module allows you to integrate X2Go client
+ support into your Python applications by providing a
+ Python-based X2Go client API (for Python 2).
+
+Package: python3-x2go
+Architecture: all
+Depends:
+ ${python3:Depends},
+ ${misc:Depends},
+ python3-gevent (>= 0.13.6-0~),
+ python3-paramiko (>= 1.15.1-0~),
+ python3-requests,
+ python3-simplejson,
+ python3-xlib,
+ nxproxy | qvd-nxproxy,
+ sshfs,
+Recommends:
+ cups-bsd | lpr,
+ pulseaudio,
+Suggests:
+ telekinesis-client,
+ mteleplayer-clientside,
+Description: Python module providing X2Go client API (Python 3)
  X2Go is a server based computing environment with
     - session resuming
     - low bandwidth support
@@ -51,7 +86,7 @@ Description: Python module providing X2Go client API
  .
  This Python module allows you to integrate X2Go client
  support into your Python applications by providing a
- Python-based X2Go client API.
+ Python-based X2Go client API (for Python 3).
 
 Package: python-x2go-doc
 Architecture: all
diff --git a/debian/python-x2go-doc.links b/debian/python-x2go-doc.links
index 163f132..0e8c762 100644
--- a/debian/python-x2go-doc.links
+++ b/debian/python-x2go-doc.links
@@ -1 +1,2 @@
+usr/share/doc/python-x2go-doc/html usr/share/doc/python3-x2go/html
 usr/share/doc/python-x2go-doc/html usr/share/doc/python-x2go/html
diff --git a/debian/python-x2go-doc.lintian-overrides b/debian/python-x2go-doc.lintian-overrides
index f3ae236..15276fa 100644
--- a/debian/python-x2go-doc.lintian-overrides
+++ b/debian/python-x2go-doc.lintian-overrides
@@ -1,2 +1,2 @@
 # epydoc produces some duplicate files, we cannot change that without great effort
-python-x2go-doc: duplicate-files
\ No newline at end of file
+python3-x2go-doc: duplicate-files
\ No newline at end of file
diff --git a/debian/python-x2go.install b/debian/python-x2go.install
index 73752c9..b2cc136 100644
--- a/debian/python-x2go.install
+++ b/debian/python-x2go.install
@@ -1 +1 @@
-usr
+usr/lib/python2*
diff --git a/debian/python3-x2go.docs b/debian/python3-x2go.docs
new file mode 100644
index 0000000..537aa79
--- /dev/null
+++ b/debian/python3-x2go.docs
@@ -0,0 +1,3 @@
+README
+README.Trinity-Desktop
+TODO
diff --git a/debian/python3-x2go.examples b/debian/python3-x2go.examples
new file mode 100644
index 0000000..e39721e
--- /dev/null
+++ b/debian/python3-x2go.examples
@@ -0,0 +1 @@
+examples/*
diff --git a/debian/python3-x2go.install b/debian/python3-x2go.install
new file mode 100644
index 0000000..4606faa
--- /dev/null
+++ b/debian/python3-x2go.install
@@ -0,0 +1 @@
+usr/lib/python3*
diff --git a/debian/rules b/debian/rules
index 8f84b83..007beaf 100755
--- a/debian/rules
+++ b/debian/rules
@@ -3,25 +3,10 @@
 # Based on sample debian/rules file - for GNU Hello (1.3).
 # Copyright 2010-2016 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
 
-WITH_PYTHON2 = $(shell test -f /usr/bin/dh_python2 && echo "--with python2")
+include /usr/share/cdbs/1/class/python-distutils.mk
+include /usr/share/cdbs/1/rules/debhelper.mk
 
-%:
-	dh ${@} ${WITH_PYTHON2}
-
-override_dh_auto_build:
+build/python-x2go-doc::
 	mkdir -p .epydoc/html
 	rm -Rf .epydoc/html/*
 	epydoc --debug -n "Python X2Go" -u http://www.x2go.org -v --html --no-private -o .epydoc/html x2go/
-	dh_auto_build
-
-# tests from upstream are currently broken...
-override_dh_auto_test:
-
-override_dh_python2:
-	rm debian/python-x2go/usr/lib/*/dist-packages/x2go/tests -Rfv
-	dh_python2
-
-override_dh_auto_clean:
-	rm -Rfv build x2go.egg-info .epydoc test.pyc
-	find x2go -name *.pyc -exec rm -fv "{}" \;
-	dh_auto_clean
diff --git a/examples/x2go_resume_session.py b/examples/x2go_resume_session.py
index 9ce00c2..7337a9e 100644
--- a/examples/x2go_resume_session.py
+++ b/examples/x2go_resume_session.py
@@ -43,7 +43,7 @@ cli.connect_session(s_uuid, password=password)
 # the next lines will resume the first session in the avail_sessions dictionary
 avail_sessions = cli.list_sessions(s_uuid)
 if avail_sessions:
-    session_info = avail_sessions.values()[0]
+    session_info = list(avail_sessions.values())[0]
     sys.stdout.write("Trying to resume session %s\n" % (session_info.name,))
     cli.resume_session(s_uuid, session_name=session_info.name)
 
@@ -56,6 +56,6 @@ if avail_sessions:
     cli.terminate_session(s_uuid)
 
 else:
-    print "No sessions to be resumed."
+    print("No sessions to be resumed.")
 
 
diff --git a/examples/x2go_start_session_with_progress_status.py b/examples/x2go_start_session_with_progress_status.py
index 8c795f9..8208a65 100644
--- a/examples/x2go_start_session_with_progress_status.py
+++ b/examples/x2go_start_session_with_progress_status.py
@@ -38,9 +38,9 @@ command  = "XFCE"
 def my_progress_bar(ps):
 
     for status in ps:
-        print '---------------'
-        print 'SESSION STATUS: ' + '#' * status + "(" + str(status) + "%%)"
-        print '---------------'
+        print('---------------')
+        print('SESSION STATUS: ' + '#' * status + "(" + str(status) + "%%)")
+        print('---------------')
 
 password = getpass.getpass()
 
diff --git a/setup.py b/setup.py
index 1d069ac..59ed68d 100755
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 # Copyright (C) 2010-2016 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
diff --git a/test.py b/test.py
index 5d9c899..4b31ff2 100755
--- a/test.py
+++ b/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 # Copyright (C) 2010-2016 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
diff --git a/x2go/__init__.py b/x2go/__init__.py
index d88f5a0..163d56a 100644
--- a/x2go/__init__.py
+++ b/x2go/__init__.py
@@ -184,9 +184,10 @@ Contact
 
 __NAME__    = 'python-x2go'
 __VERSION__ = '0.5.0.7'
+__PACKAGE__ = 'x2go'
 
 import os
-from defaults import X2GOCLIENT_OS
+from .defaults import X2GOCLIENT_OS
 
 if X2GOCLIENT_OS != 'Windows':
     # enforce "ares" resolve in gevent (>= 1.0~)...
@@ -195,28 +196,28 @@ if X2GOCLIENT_OS != 'Windows':
 from gevent import monkey
 monkey.patch_all()
 
-import utils
+import .utils
 
-from client import X2GoClient
-from backends.profiles.file import X2GoSessionProfiles
-from backends.printing.file import X2GoClientPrinting
-from backends.settings.file import X2GoClientSettings
-from session import X2GoSession
-from sshproxy import X2GoSSHProxy
-from x2go_exceptions import *
-from log import *
+from .client import X2GoClient
+from .backends.profiles.file import X2GoSessionProfiles
+from .backends.printing.file import X2GoClientPrinting
+from .backends.settings.file import X2GoClientSettings
+from .session import X2GoSession
+from .sshproxy import X2GoSSHProxy
+from .x2go_exceptions import *
+from .log import *
 
-from cleanup import x2go_cleanup
+from .cleanup import x2go_cleanup
 
-from defaults import CURRENT_LOCAL_USER
-from defaults import LOCAL_HOME
-from defaults import X2GO_CLIENT_ROOTDIR
-from defaults import X2GO_SESSIONS_ROOTDIR
-from defaults import X2GO_SSH_ROOTDIR
-from defaults import BACKENDS
+from .defaults import CURRENT_LOCAL_USER
+from .defaults import LOCAL_HOME
+from .defaults import X2GO_CLIENT_ROOTDIR
+from .defaults import X2GO_SESSIONS_ROOTDIR
+from .defaults import X2GO_SSH_ROOTDIR
+from .defaults import BACKENDS
 
 if X2GOCLIENT_OS == 'Windows':
-    from xserver import X2GoClientXConfig, X2GoXServer
+    from .xserver import X2GoClientXConfig, X2GoXServer
 
 # compat section
 X2goClient = X2GoClient
diff --git a/x2go/_paramiko.py b/x2go/_paramiko.py
index 70e61d2..746fc3d 100644
--- a/x2go/_paramiko.py
+++ b/x2go/_paramiko.py
@@ -22,6 +22,8 @@ Monkey Patch and feature map for Python Paramiko
 
 """
 
+__PACKAGE__ = 'x2go'
+
 import paramiko
 import re
 try:
@@ -29,7 +31,7 @@ try:
 except ImportError:
     SSH_PORT=22
 import platform
-from utils import compare_versions
+from x2go.utils import compare_versions
 
 PARAMIKO_VERSION = paramiko.__version__.split()[0]
 PARAMIKO_FEATURE = {
@@ -67,9 +69,9 @@ def _SSHClient_save_host_keys(self, filename):
     f = open(filename, 'w')
     #f.write('# SSH host keys collected by paramiko\n')
     _host_keys = self.get_host_keys()
-    for hostname, keys in _host_keys.iteritems():
+    for hostname, keys in _host_keys.items():
 
-        for keytype, key in keys.iteritems():
+        for keytype, key in keys.items():
             f.write('%s %s %s\n' % (hostname, keytype, key.get_base64()))
 
     f.close()
diff --git a/x2go/backends/control/plain.py b/x2go/backends/control/plain.py
index 3dcc3ef..34a32e0 100644
--- a/x2go/backends/control/plain.py
+++ b/x2go/backends/control/plain.py
@@ -36,7 +36,7 @@ import random
 import re
 import locale
 import threading
-import cStringIO
+import io
 import base64
 import uuid
 
@@ -458,7 +458,7 @@ class X2GoControlSession(paramiko.SSHClient):
         @raise X2GoControlSessionException: if the command execution failed (due to a lost connection)
 
         """
-        if type(cmd_line) == types.ListType:
+        if type(cmd_line) == list:
             cmd = " ".join(cmd_line)
         else:
             cmd = cmd_line
@@ -468,7 +468,7 @@ class X2GoControlSession(paramiko.SSHClient):
 
         if self.session_died:
             self.logger("control session seams to be dead, not executing command ,,%s'' on X2Go server %s" % (_rerewrite_blanks(cmd), self.profile_name,), loglevel=loglevel)
-            return (cStringIO.StringIO(), cStringIO.StringIO(), cStringIO.StringIO('failed to execute command'))
+            return (io.StringIO(), io.StringIO(), io.StringIO('failed to execute command'))
 
         self._transport_lock.acquire()
 
@@ -532,7 +532,7 @@ class X2GoControlSession(paramiko.SSHClient):
 
         sanitized_stdout = ''
         is_x2go_data = False
-        for line in raw_stdout.split('\n'):
+        for line in raw_stdout.decode().split('\n'):
             if line.startswith('X2GODATABEGIN:'+cmd_uuid):
                 is_x2go_data = True
                 continue
@@ -540,7 +540,7 @@ class X2GoControlSession(paramiko.SSHClient):
             if line.startswith('X2GODATAEND:'+cmd_uuid): break
             sanitized_stdout += line + "\n"
 
-        _stdout_new = cStringIO.StringIO(sanitized_stdout)
+        _stdout_new = io.StringIO(sanitized_stdout)
 
         _retval = (_stdin, _stdout_new, _stderr)
         return _retval
@@ -637,7 +637,7 @@ class X2GoControlSession(paramiko.SSHClient):
         @rtype: C{list}
 
         """
-        if not self._remote_group.has_key(group):
+        if group not in self._remote_group:
             (stdin, stdout, stderr) = self._x2go_exec_command('getent group %s | cut -d":" -f4' % group)
             self._remote_group[group] = stdout.read().split('\n')[0].split(',')
             self.logger('remote %s group: %s' % (group, self._remote_group[group]), loglevel=log.loglevel_DEBUG)
@@ -882,18 +882,18 @@ class X2GoControlSession(paramiko.SSHClient):
         """
         _fake_hostname = None
 
-        if hostname and type(hostname) not in (types.UnicodeType, types.StringType):
+        if hostname and type(hostname) not in (str, bytes):
             hostname = [hostname]
-        if hostname and type(hostname) is types.ListType:
+        if hostname and type(hostname) is list:
             hostname = random.choice(hostname)
 
         if not username:
             self.logger('no username specified, cannot connect without username', loglevel=log.loglevel_ERROR)
             raise paramiko.AuthenticationException('no username specified, cannot connect without username')
 
-        if type(password) not in (types.StringType, types.UnicodeType):
+        if type(password) not in (bytes, str):
             password = ''
-        if type(sshproxy_password) not in (types.StringType, types.UnicodeType):
+        if type(sshproxy_password) not in (bytes, str):
             sshproxy_password = ''
 
         if unique_hostkey_aliases is None:
@@ -1004,7 +1004,7 @@ class X2GoControlSession(paramiko.SSHClient):
                                                key_filename=None, timeout=timeout, allow_agent=allow_agent,
                                                look_for_keys=look_for_keys)
 
-            except (paramiko.PasswordRequiredException, paramiko.SSHException), e:
+            except (paramiko.PasswordRequiredException, paramiko.SSHException) as e:
                 self.close()
                 if type(e) == paramiko.SSHException and str(e).startswith('Two-factor authentication requires a password'):
                     self.logger('X2Go Server requests two-factor authentication', loglevel=log.loglevel_NOTICE)
@@ -1038,11 +1038,11 @@ class X2GoControlSession(paramiko.SSHClient):
                                                            key_filename=None, timeout=timeout, allow_agent=allow_agent,
                                                            look_for_keys=look_for_keys)
 
-                    except paramiko.AuthenticationException, auth_e:
+                    except paramiko.AuthenticationException as auth_e:
                         # the provided password cannot be used to unlock any private SSH key file (i.e. wrong password)
                         raise paramiko.AuthenticationException(str(auth_e))
 
-                    except paramiko.SSHException, auth_e:
+                    except paramiko.SSHException as auth_e:
                         if str(auth_e) == 'No authentication methods available':
                             raise paramiko.AuthenticationException('Interactive password authentication required!')
                         else:
@@ -1057,7 +1057,7 @@ class X2GoControlSession(paramiko.SSHClient):
                         self.sshproxy_session.stop_thread()
                     raise e
 
-            except paramiko.AuthenticationException, e:
+            except paramiko.AuthenticationException as e:
                 self.close()
                 if password:
                     self.logger('next auth mechanism we\'ll try is password authentication', loglevel=log.loglevel_DEBUG)
@@ -1075,7 +1075,7 @@ class X2GoControlSession(paramiko.SSHClient):
                         self.sshproxy_session.stop_thread()
                     raise e
 
-            except paramiko.SSHException, e:
+            except paramiko.SSHException as e:
                 if str(e) == 'No authentication methods available':
                     raise paramiko.AuthenticationException('Interactive password authentication required!')
                 else:
@@ -1142,7 +1142,7 @@ class X2GoControlSession(paramiko.SSHClient):
                         self.agent_chan = ssh_transport.open_session()
                         self.agent_handler = paramiko.agent.AgentRequestHandler(self.agent_chan)
                         self.logger('Requesting SSH agent forwarding for control session of connected session profile %s' % self.profile_name, loglevel=log.loglevel_INFO)
-                    except EOFError, e:
+                    except EOFError as e:
                         # if we come across an EOFError here, we must assume the session is dead...
                         self.session_died = True
                         raise x2go_exceptions.X2GoControlSessionException('The SSH connection was dropped while setting up SSH agent forwarding socket.')
@@ -1171,10 +1171,10 @@ class X2GoControlSession(paramiko.SSHClient):
         @type terminal_session: C{X2GoTerminalSession*}
 
         """
-        for t_name in self.associated_terminals.keys():
+        for t_name in list(self.associated_terminals.keys()):
             if self.associated_terminals[t_name] == terminal_session:
                 del self.associated_terminals[t_name]
-                if self.terminated_terminals.has_key(t_name):
+                if t_name in self.terminated_terminals:
                     del self.terminated_terminals[t_name]
 
     def disconnect(self):
@@ -1186,8 +1186,8 @@ class X2GoControlSession(paramiko.SSHClient):
 
         """
         if self.associated_terminals:
-            t_names = self.associated_terminals.keys()
-            for t_obj in self.associated_terminals.values():
+            t_names = list(self.associated_terminals.keys())
+            for t_obj in list(self.associated_terminals.values()):
                 try:
                     if not self.session_died:
                         t_obj.suspend()
@@ -1312,7 +1312,7 @@ class X2GoControlSession(paramiko.SSHClient):
 
         if 'X2GO_PUBLISHED_APPLICATIONS' in self.get_server_features():
             if self._published_applications_menu is {} or \
-               not self._published_applications_menu.has_key(lang) or \
+               lang not in self._published_applications_menu or \
                raw or very_raw or refresh or \
                (self.published_applications_no_submenus != max_no_submenus):
 
@@ -1373,7 +1373,7 @@ class X2GoControlSession(paramiko.SSHClient):
                         'TOP': [],
                     }
                 }
-                _empty_menus = _category_map[lang].keys()
+                _empty_menus = list(_category_map[lang].keys())
 
                 for item in _menu:
 
@@ -1462,7 +1462,7 @@ class X2GoControlSession(paramiko.SSHClient):
                 for _cat in _empty_menus:
                     del _category_map[lang][_cat]
 
-                for _cat in _category_map[lang].keys():
+                for _cat in list(_category_map[lang].keys()):
                     _sorted = sorted(_category_map[lang][_cat], key=lambda k: k['name'])
                     _category_map[lang][_cat] = _sorted
 
@@ -1494,7 +1494,7 @@ class X2GoControlSession(paramiko.SSHClient):
         @rtype: C{bool}
 
         """
-        if 'session_name' in kwargs.keys():
+        if 'session_name' in list(kwargs.keys()):
             del kwargs['session_name']
         return self.resume(**kwargs)
 
@@ -1745,8 +1745,8 @@ class X2GoControlSession(paramiko.SSHClient):
 
             # update internal variables when list_sessions() is called
             if _success and not self.session_died:
-                for _session_name, _terminal in self.associated_terminals.items():
-                    if _session_name in _listsessions.keys():
+                for _session_name, _terminal in list(self.associated_terminals.items()):
+                    if _session_name in list(_listsessions.keys()):
                         # update the whole session_info object within the terminal session
                         if hasattr(self.associated_terminals[_session_name], 'session_info') and not self.associated_terminals[_session_name].is_session_info_protected():
                             self.associated_terminals[_session_name].session_info.update(_listsessions[_session_name])
@@ -1775,11 +1775,11 @@ class X2GoControlSession(paramiko.SSHClient):
         """
         session_list = self.list_sessions()
         if published_applications:
-            session_names = session_list.keys()
+            session_names = list(session_list.keys())
         else:
-            session_names = [ _sn for _sn in session_list.keys() if not session_list[_sn].is_published_applications_provider() ]
+            session_names = [ _sn for _sn in list(session_list.keys()) if not session_list[_sn].is_published_applications_provider() ]
         for session_name in session_names:
-            if self.associated_terminals.has_key(session_name):
+            if session_name in self.associated_terminals:
                 self.associated_terminals[session_name].terminate()
                 if destroy_terminals:
                     if self.associated_terminals[session_name] is not None:
@@ -1813,7 +1813,7 @@ class X2GoControlSession(paramiko.SSHClient):
 
         """
         session_infos = self.list_sessions()
-        if session_name in session_infos.keys():
+        if session_name in list(session_infos.keys()):
             return session_infos[session_name].is_running()
         return None
 
@@ -1827,7 +1827,7 @@ class X2GoControlSession(paramiko.SSHClient):
 
         """
         session_infos = self.list_sessions()
-        if session_name in session_infos.keys():
+        if session_name in list(session_infos.keys()):
             return session_infos[session_name].is_suspended()
         return None
 
@@ -1845,7 +1845,7 @@ class X2GoControlSession(paramiko.SSHClient):
         session_infos = self.list_sessions()
         if session_name in self.terminated_terminals:
             return True
-        if session_name not in session_infos.keys() and session_name in self.associated_terminals.keys():
+        if session_name not in list(session_infos.keys()) and session_name in list(self.associated_terminals.keys()):
             # do a post-mortem tidy up
             self.terminate(session_name)
             return True
@@ -1867,14 +1867,14 @@ class X2GoControlSession(paramiko.SSHClient):
 
         """
         _ret = False
-        _session_names = [ t.get_session_name() for t in self.associated_terminals.values() ]
+        _session_names = [ t.get_session_name() for t in list(self.associated_terminals.values()) ]
         if session_name in _session_names:
 
             self.logger('suspending associated terminal session: %s' % session_name, loglevel=log.loglevel_DEBUG)
             (stdin, stdout, stderr) = self._x2go_exec_command("x2gosuspend-session %s" % session_name, loglevel=log.loglevel_DEBUG)
             stdout.read()
             stderr.read()
-            if self.associated_terminals.has_key(session_name):
+            if session_name in self.associated_terminals:
                 if self.associated_terminals[session_name] is not None:
                     self.associated_terminals[session_name].__del__()
                 try: del self.associated_terminals[session_name]
@@ -1905,7 +1905,7 @@ class X2GoControlSession(paramiko.SSHClient):
         """
 
         _ret = False
-        if session_name in self.associated_terminals.keys():
+        if session_name in list(self.associated_terminals.keys()):
 
             self.logger('terminating associated session: %s' % session_name, loglevel=log.loglevel_DEBUG)
             (stdin, stdout, stderr) = self._x2go_exec_command("x2goterminate-session %s" % session_name, loglevel=log.loglevel_DEBUG)
diff --git a/x2go/backends/info/plain.py b/x2go/backends/info/plain.py
index 4823a05..51558c3 100644
--- a/x2go/backends/info/plain.py
+++ b/x2go/backends/info/plain.py
@@ -73,21 +73,21 @@ class X2GoServerSessionInfo(object):
             self.username = l[11]
             self.sshfs_port = int(l[13])
             self.local_container = ''
-        except IndexError, e:
+        except IndexError as e:
             # DEBUGGING CODE
             raise e
-        except ValueError, e:
+        except ValueError as e:
             # DEBUGGING CODE
             raise e
 
         # retrieve Telekinesis ports from list of sessions...
         try:
             self.tekictrl_port = int(l[14])
-        except (IndexError, ValueError), e:
+        except (IndexError, ValueError) as e:
             self.tekictrl_port = -1
         try:
             self.tekidata_port = int(l[15])
-        except (IndexError, ValueError), e:
+        except (IndexError, ValueError) as e:
             self.tekidata_port = -1
 
     def is_published_applications_provider(self):
@@ -118,6 +118,7 @@ class X2GoServerSessionInfo(object):
         @rtype: C{str}
         """
         cmd = self.name.split('_')[1]
+        print(cmd)
         session_type = cmd[2]
         if session_type == 'R' and self.is_published_applications_provider():
             session_type = 'P'
@@ -184,21 +185,21 @@ class X2GoServerSessionInfo(object):
             self.status = 'R'
             self.local_container = ''
             self.remote_container = ''
-        except IndexError, e:
+        except IndexError as e:
             # DEBUGGING CODE
             raise e
-        except ValueError, e:
+        except ValueError as e:
             # DEBUGGING CODE
             raise e
 
         # retrieve Telekinesis ports from x2gostartagent output
         try:
             self.tekictrl_port = int(l[7])
-        except (IndexError, ValueError), e:
+        except (IndexError, ValueError) as e:
             self.tekictrl_port = -1
         try:
             self.tekidata_port = int(l[8])
-        except (IndexError, ValueError), e:
+        except (IndexError, ValueError) as e:
             self.tekidata_port = -1
 
     def initialize(self, x2go_output, username='', hostname='', local_container='', remote_container=''):
@@ -371,7 +372,7 @@ class X2GoServerSessionList(object):
             value = value.lstrip(':')
             if '.' in value: value = value.split('.')[0]
 
-        for session in self.sessions.values():
+        for session in list(self.sessions.values()):
             try:
                 if str(getattr(session, property_name)) == str(value):
                     if hostname is None or session.hostname == hostname:
diff --git a/x2go/backends/printing/file.py b/x2go/backends/printing/file.py
index 65b0f0a..bdb14c6 100644
--- a/x2go/backends/printing/file.py
+++ b/x2go/backends/printing/file.py
@@ -101,10 +101,10 @@ class X2GoClientPrinting(inifiles.X2GoIniFile):
         X2Go client »printing« configuration file.
 
         """
-        _general_pdfview = self.get('General', 'pdfview', key_type=types.BooleanType)
-        _view_open = self.get('view', 'open', key_type=types.BooleanType)
-        _print_startcmd = self.get('print', 'startcmd', key_type=types.BooleanType)
-        _show_dialog = self.get('General', 'showdialog', key_type=types.BooleanType)
+        _general_pdfview = self.get('General', 'pdfview', key_type=bool)
+        _view_open = self.get('view', 'open', key_type=bool)
+        _print_startcmd = self.get('print', 'startcmd', key_type=bool)
+        _show_dialog = self.get('General', 'showdialog', key_type=bool)
 
         if _show_dialog and self.client_instance is not None:
             self._print_action = printactions.X2GoPrintActionDIALOG(client_instance=self.client_instance, logger=self.logger)
@@ -175,7 +175,7 @@ class X2GoClientPrinting(inifiles.X2GoIniFile):
         @raise X2GoClientPrintingException: if the printing property does not exist
 
         """
-        if print_property in _print_property_map.keys():
+        if print_property in list(_print_property_map.keys()):
             _ini_section = _print_property_map[print_property]['ini_section']
             _ini_option = _print_property_map[print_property]['ini_option']
             return self.get_value(_ini_section, _ini_option)
@@ -194,11 +194,11 @@ class X2GoClientPrinting(inifiles.X2GoIniFile):
         @raise X2GoClientPrintingException: if the printing property does not exist or if there is a type mismatch
 
         """
-        if print_property in _print_property_map.keys():
+        if print_property in list(_print_property_map.keys()):
             _ini_section = _print_property_map[print_property]['ini_section']
             _ini_option = _print_property_map[print_property]['ini_option']
             _default_type = self.get_type(_ini_section, _ini_option)
-            if type(value) is types.UnicodeType:
+            if type(value) is str:
                 value = value.encode('utf-8')
             if  _default_type != type(value):
                 raise x2go_exceptions.X2GoClientPrintingException('Type mismatch error for property ,,%s\'\' - is: %s, should be: %s' % (print_property, str(type(value)), str(_default_type)))
@@ -239,6 +239,6 @@ class X2GoClientPrinting(inifiles.X2GoIniFile):
             self.update_value('General', 'pdfview', False)
             self.update_value('print', 'startcmd', True)
 
-        for print_property in print_properties.keys():
+        for print_property in list(print_properties.keys()):
             self.set_property(print_property, print_properties[print_property])
 
diff --git a/x2go/backends/profiles/base.py b/x2go/backends/profiles/base.py
index 4e08034..3e02492 100644
--- a/x2go/backends/profiles/base.py
+++ b/x2go/backends/profiles/base.py
@@ -126,17 +126,17 @@ class X2GoSessionProfiles():
 
         # scan for duplicate profile names and handle them...
         scan_profile_names = {}
-        for profile_id in self.session_profiles.keys():
+        for profile_id in list(self.session_profiles.keys()):
             profile_name = self.to_profile_name(profile_id)
-            if profile_name not in scan_profile_names.keys():
+            if profile_name not in list(scan_profile_names.keys()):
                 scan_profile_names[profile_name] = [profile_id]
             else:
                 scan_profile_names[profile_name].append(profile_id)
         _duplicates = {}
-        for profile_name in scan_profile_names.keys():
+        for profile_name in list(scan_profile_names.keys()):
             if len(scan_profile_names[profile_name]) > 1:
                 _duplicates[profile_name] = scan_profile_names[profile_name]
-        for profile_name in _duplicates.keys():
+        for profile_name in list(_duplicates.keys()):
             i = 1
             for profile_id in _duplicates[profile_name]:
                 self.update_value(None, 'name', '{name} ({i})'.format(name=profile_name, i=i), profile_id=profile_id)
@@ -168,24 +168,24 @@ class X2GoSessionProfiles():
         """
         _profile_id = self.check_profile_id_or_name(profile_id_or_name)
 
-        if not self._profile_metatypes.has_key(_profile_id) or force:
+        if _profile_id not in self._profile_metatypes or force:
             _config = self.get_profile_config(_profile_id)
             if _config['host']:
                 if _config['rdpserver'] and _config['command'] == 'RDP':
                     _metatype = 'RDP/proxy'
                 elif _config['published']:
 
-                    if _config['command'] in _X2GO_DESKTOPSESSIONS.keys():
+                    if _config['command'] in list(_X2GO_DESKTOPSESSIONS.keys()):
                         _metatype = '%s + Published Applications' % _config['command']
                     else:
                         _metatype = 'Published Applications'
 
                 elif _config['rootless']:
                     _metatype = 'Single Applications'
-                elif _config['command'] in _X2GO_DESKTOPSESSIONS.keys():
+                elif _config['command'] in list(_X2GO_DESKTOPSESSIONS.keys()):
                     _metatype = '%s Desktop' % _config['command']
-                elif _config['command'] in _X2GO_DESKTOPSESSIONS.values():
-                    _metatype = '%s Desktop' % [ s for s in _X2GO_DESKTOPSESSIONS.keys() if _config['command'] == _X2GO_DESKTOPSESSIONS[s] ][0]
+                elif _config['command'] in list(_X2GO_DESKTOPSESSIONS.values()):
+                    _metatype = '%s Desktop' % [ s for s in list(_X2GO_DESKTOPSESSIONS.keys()) if _config['command'] == _X2GO_DESKTOPSESSIONS[s] ][0]
                 else:
                     _metatype = 'CUSTOM Desktop'
             else:
@@ -193,7 +193,7 @@ class X2GoSessionProfiles():
                     _metatype = 'RDP/direct'
                 else:
                     _metatype = 'not supported'
-            self._profile_metatypes[_profile_id] = unicode(_metatype)
+            self._profile_metatypes[_profile_id] = str(_metatype)
         else:
             return self._profile_metatypes[_profile_id]
 
@@ -311,7 +311,7 @@ class X2GoSessionProfiles():
         try:
             return type(self.defaultSessionProfile[option])
         except KeyError:
-            return types.StringType
+            return bytes
 
     def get_profile_config(self, profile_id_or_name=None, parameter=None, profile_id=None):
         """\
@@ -337,10 +337,10 @@ class X2GoSessionProfiles():
         for option in parameters:
             value = self._get_profile_parameter(_profile_id, option, key_type=self.get_profile_option_type(option))
 
-            if type(value) is types.StringType:
-                value = unicode(value)
+            if type(value) is bytes:
+                value = str(value)
 
-            if option == 'export' and type(value) is types.UnicodeType:
+            if option == 'export' and type(value) is str:
 
                 _value = value.replace(',', ';').strip().strip('"').strip().strip(';').strip()
                 value = {}
@@ -355,7 +355,7 @@ class X2GoSessionProfiles():
             _profile_config[option] = value
 
         if parameter is not None:
-            if parameter in _profile_config.keys():
+            if parameter in list(_profile_config.keys()):
                 value = _profile_config[parameter]
                 return value
             else:
@@ -403,7 +403,7 @@ class X2GoSessionProfiles():
         """
         if not self._cached_profile_ids:
             self._update_profile_ids_cache()
-        return self._cached_profile_ids.keys()
+        return list(self._cached_profile_ids.keys())
 
     def _get_profile_ids(self):
         """\
@@ -427,7 +427,7 @@ class X2GoSessionProfiles():
         @rtype: C{bool}
 
         """
-        return unicode(profile_id) in self.profile_ids
+        return str(profile_id) in self.profile_ids
 
     @property
     def profile_names(self):
@@ -437,7 +437,7 @@ class X2GoSessionProfiles():
         """
         if not self._cached_profile_ids:
             self._update_profile_ids_cache()
-        return  self._cached_profile_ids.values()
+        return  list(self._cached_profile_ids.values())
 
     def has_profile_name(self, profile_name):
         """\
@@ -450,7 +450,7 @@ class X2GoSessionProfiles():
         @rtype: C{bool}
 
         """
-        return unicode(profile_name) in self.profile_names
+        return str(profile_name) in self.profile_names
 
     def to_profile_id(self, profile_name):
         """\
@@ -465,7 +465,7 @@ class X2GoSessionProfiles():
         """
         _profile_ids = [ p for p in self.profile_ids if self._cached_profile_ids[p] == profile_name ]
         if len(_profile_ids) == 1:
-            return unicode(_profile_ids[0])
+            return str(_profile_ids[0])
         elif len(_profile_ids) == 0:
             return None
         else:
@@ -484,9 +484,9 @@ class X2GoSessionProfiles():
         """
         try:
             _profile_name = self.get_profile_config(profile_id=profile_id, parameter='name')
-            return unicode(_profile_name)
+            return str(_profile_name)
         except:
-            return u''
+            return ''
 
     def add_profile(self, profile_id=None, force_add=False, **kwargs):
         """\
@@ -505,7 +505,7 @@ class X2GoSessionProfiles():
             profile_id = utils._genSessionProfileId()
             self.session_profiles[profile_id] = self.default_profile_config()
 
-        if 'name' not in kwargs.keys():
+        if 'name' not in list(kwargs.keys()):
             raise X2GoProfileException('session profile parameter ,,name\'\' is missing in method parameters')
 
         if kwargs['name'] in self.profile_names and not force_add:
@@ -513,17 +513,17 @@ class X2GoSessionProfiles():
 
         self._cached_profile_ids[profile_id] = kwargs['name']
 
-        for key, value in kwargs.items():
+        for key, value in list(kwargs.items()):
             self.update_value(None, key, value, profile_id=profile_id)
 
         _default_session_profile = self.default_profile_config()
-        for key, value in _default_session_profile.items():
+        for key, value in list(_default_session_profile.items()):
             if key in kwargs: continue
             self.update_value(None, key, value, profile_id=profile_id)
 
         self._cached_profile_ids = {}
 
-        return unicode(profile_id)
+        return str(profile_id)
 
     def delete_profile(self, profile_id_or_name):
         """\
@@ -585,9 +585,9 @@ class X2GoSessionProfiles():
                         raise X2GoProfileException('a profile of name ,,%s\'\' already exists' % profile_name)
                     self._cached_profile_ids[profile_id] = profile_name
 
-        if option == 'export' and type(value) == types.DictType:
+        if option == 'export' and type(value) == dict:
             _strvalue = '"'
-            for folder in value.keys():
+            for folder in list(value.keys()):
                 _strvalue += "%s:%s;" % (folder, int(value[folder]))
             _strvalue += '"'
             _strvalue = _strvalue.replace('""', '')
@@ -597,9 +597,9 @@ class X2GoSessionProfiles():
             _host = self.get_profile_config(profile_id=profile_id, parameter='host')
             if _host != value and _host is not None:
                 self._profiles_need_profile_id_renewal.append(profile_id)
-            if type(value) is types.TupleType:
+            if type(value) is tuple:
                 value = list(value)
-            if type(value) is not types.ListType:
+            if type(value) is not list:
                 value = value.split(',')
 
         self._update_value(profile_id, option, value)
@@ -635,7 +635,7 @@ class X2GoSessionProfiles():
         else:
             raise X2GoProfileException('No session profile with id or name ,,%s\'\' exists.' % profile_id_or_name)
         if _profile_id is not None:
-            _profile_id = unicode(_profile_id)
+            _profile_id = str(_profile_id)
         return _profile_id
 
     def to_session_params(self, profile_id_or_name=None, profile_id=None):
@@ -710,7 +710,7 @@ class X2GoSessionProfiles():
         @rtype: C{list}
 
         """
-        return unicode(self._get_server_hostname(profile_id))
+        return str(self._get_server_hostname(profile_id))
 
     def _get_server_hostname(self, profile_id):
         """\
@@ -725,7 +725,7 @@ class X2GoSessionProfiles():
         @rtype: C{list}
 
         """
-        return u'localhost'
+        return 'localhost'
 
     def get_server_port(self, profile_id):
         """\
diff --git a/x2go/backends/profiles/file.py b/x2go/backends/profiles/file.py
index 65a4542..cb029c3 100644
--- a/x2go/backends/profiles/file.py
+++ b/x2go/backends/profiles/file.py
@@ -86,7 +86,7 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles, inifiles.X2GoIniFile):
         session_profiles = [ p for p in self.iniConfig.sections() if p not in self._non_profile_sections and p != 'none' ]
         _session_profiles_dict = {}
         for session_profile in session_profiles:
-            for key, default_value in self.defaultSessionProfile.iteritems():
+            for key, default_value in self.defaultSessionProfile.items():
                 if not self.iniConfig.has_option(session_profile, key):
                     self._storeValue(session_profile, key, default_value)
             # update cached meta type session profile information
diff --git a/x2go/backends/profiles/httpbroker.py b/x2go/backends/profiles/httpbroker.py
index 7925a5d..72b7bdb 100644
--- a/x2go/backends/profiles/httpbroker.py
+++ b/x2go/backends/profiles/httpbroker.py
@@ -206,7 +206,7 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
                 payload = json.loads(r.text)
                 if not self.broker_authid and not self.broker_password:
                     self.broker_noauth = True
-                elif payload.has_key('next-authid'):
+                elif 'next-authid' in payload:
                     self.broker_authid = payload['next-authid']
                 self.broker_username = broker_username or ''
                 self.broker_password = broker_password or ''
@@ -293,9 +293,9 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
                 raise x2go.x2go_exceptions.X2GoBrokerConnectionException('Failed to connect to URL %s' % self.broker_url)
             if r.status_code == 200 and r.headers['content-type'].startswith("text/json"):
                 payload = json.loads(r.text)
-                if payload.has_key('next-authid'):
+                if 'next-authid' in payload:
                     self.broker_authid = payload['next-authid']
-                if payload.has_key('mutable_profile_ids'):
+                if 'mutable_profile_ids' in payload:
                     self._mutable_profile_ids = payload['mutable_profile_ids']
                 self._broker_auth_successful = True
                 return payload['profiles'] if payload['task'] == 'listprofiles' else {}
@@ -319,7 +319,7 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
 
         """
         if self.broker_url is not None:
-            if not self._broker_profile_cache.has_key(profile_id) or not self._broker_profile_cache[profile_id]:
+            if profile_id not in self._broker_profile_cache or not self._broker_profile_cache[profile_id]:
                 request_data = {
                     'task': 'selectsession',
                     'profile-id': profile_id,
@@ -342,7 +342,7 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
                     raise x2go.x2go_exceptions.X2GoBrokerConnectionException('Failed to connect to URL %s' % self.broker_url)
                 if r.status_code == 200 and r.headers['content-type'].startswith("text/json"):
                     payload = json.loads(r.text)
-                    if payload.has_key('next-authid'):
+                    if 'next-authid' in payload:
                         self.broker_authid = payload['next-authid']
                     self._broker_profile_cache[profile_id] = payload['selected_session'] if payload['task'] == 'selectsession' else {}
                     self._broker_auth_successful = True
@@ -354,8 +354,8 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
         return {}
 
     def _init_profile_cache(self, profile_id):
-        if self._broker_profile_cache.has_key(unicode(profile_id)):
-            del self._broker_profile_cache[unicode(profile_id)]
+        if str(profile_id) in self._broker_profile_cache:
+            del self._broker_profile_cache[str(profile_id)]
 
     def _populate_session_profiles(self):
         """\
@@ -374,12 +374,12 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
             _session_profiles = copy.deepcopy(session_profiles)
 
             for session_profile in _session_profiles:
-                session_profile = unicode(session_profile)
-                for key, default_value in self.defaultSessionProfile.iteritems():
-                    key = unicode(key)
-                    if type(default_value) is types.StringType:
-                        default_value = unicode(default_value)
-                    if not session_profiles[session_profile].has_key(key):
+                session_profile = str(session_profile)
+                for key, default_value in self.defaultSessionProfile.items():
+                    key = str(key)
+                    if type(default_value) is bytes:
+                        default_value = str(default_value)
+                    if key not in session_profiles[session_profile]:
                         session_profiles[session_profile][key] = default_value
 
         else:
@@ -388,35 +388,35 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
         return session_profiles
 
     def _is_mutable(self, profile_id):
-        if type(self._mutable_profile_ids) is types.ListType and profile_id in self._mutable_profile_ids:
+        if type(self._mutable_profile_ids) is list and profile_id in self._mutable_profile_ids:
             return True
         return False
 
     def _supports_mutable_profiles(self):
-        if type(self._mutable_profile_ids) is types.ListType:
+        if type(self._mutable_profile_ids) is list:
             return True
         return False
 
     def _write(self):
-        print "not suported, yet"
+        print("not suported, yet")
 
     def _delete_profile(self, profile_id):
-        del self.session_profiles[unicode(profile_id)]
+        del self.session_profiles[str(profile_id)]
 
     def _update_value(self, profile_id, option, value):
-        if type(value) is types.StringType:
-            value = unicode(value)
-        self.session_profiles[unicode(profile_id)][unicode(option)] = value
+        if type(value) is bytes:
+            value = str(value)
+        self.session_profiles[str(profile_id)][str(option)] = value
 
     def _get_profile_parameter(self, profile_id, option, key_type):
-        return key_type(self.session_profiles[unicode(profile_id)][unicode(option)])
+        return key_type(self.session_profiles[str(profile_id)][str(option)])
 
     def _get_profile_options(self, profile_id):
-        return self.session_profiles[unicode(profile_id)].keys()
+        return list(self.session_profiles[str(profile_id)].keys())
 
     def _get_profile_ids(self):
-        self.session_profiles.keys()
-        return self.session_profiles.keys()
+        list(self.session_profiles.keys())
+        return list(self.session_profiles.keys())
 
     def _get_server_hostname(self, profile_id):
         selected_session = self.broker_selectsession(profile_id)
@@ -428,7 +428,7 @@ class X2GoSessionProfiles(base.X2GoSessionProfiles):
 
     def _get_pkey_object(self, profile_id):
         selected_session = self.broker_selectsession(profile_id)
-        if selected_session.has_key('authentication_pubkey') and selected_session['authentication_pubkey'] == 'ACCEPTED':
+        if 'authentication_pubkey' in selected_session and selected_session['authentication_pubkey'] == 'ACCEPTED':
             time.sleep(2)
             return self.broker_my_privkey
         return None
diff --git a/x2go/backends/proxy/base.py b/x2go/backends/proxy/base.py
index d12ee1f..10c4c21 100644
--- a/x2go/backends/proxy/base.py
+++ b/x2go/backends/proxy/base.py
@@ -135,7 +135,7 @@ class X2GoProxy(threading.Thread):
             self.logger('Shutting down X2Go proxy subprocess', loglevel=log.loglevel_DEBUG)
             try:
                 self.proxy.kill()
-            except OSError, e:
+            except OSError as e:
                 self.logger('X2Go proxy shutdown gave a message that we may ignore: %s' % str(e), loglevel=log.loglevel_WARN)
             self.proxy = None
         if self.fw_tunnel is not None:
@@ -172,7 +172,7 @@ class X2GoProxy(threading.Thread):
 
         try:
             os.makedirs(self.session_info.local_container)
-        except OSError, e:
+        except OSError as e:
             if e.errno == 17:
                 # file exists
                 pass
@@ -230,7 +230,7 @@ class X2GoProxy(threading.Thread):
         try:
             p.terminate()
             self.logger('terminating proxy: %s' % p, loglevel=log.loglevel_DEBUG)
-        except OSError, e:
+        except OSError as e:
             if e.errno == 3:
                 # No such process
                 pass
diff --git a/x2go/backends/proxy/nx3.py b/x2go/backends/proxy/nx3.py
index 3a467e4..4f9fcbb 100644
--- a/x2go/backends/proxy/nx3.py
+++ b/x2go/backends/proxy/nx3.py
@@ -56,7 +56,7 @@ class X2GoProxy(base.X2GoProxy):
                 os.path.join(os.environ["ProgramFiles"], os.path.normpath("NX Client for Windows/bin/nxproxy.exe")),
                 os.path.normpath("../pyhoca-contrib/mswin/nxproxy-mswin/nxproxy-3.5.0.27_cygwin-2015-10-18/nxproxy.exe"),
             ]
-            if os.environ.has_key('NXPROXY_BINARY'):
+            if 'NXPROXY_BINARY' in os.environ:
                 _nxproxy_paths.insert(0, os.environ['NXPROXY_BINARY'])
             for _nxproxy_cmd in _nxproxy_paths:
                 if os.path.exists(_nxproxy_cmd):
diff --git a/x2go/backends/terminal/plain.py b/x2go/backends/terminal/plain.py
index 1ea43ea..c80565f 100644
--- a/x2go/backends/terminal/plain.py
+++ b/x2go/backends/terminal/plain.py
@@ -30,7 +30,7 @@ __NAME__ = 'x2goterminalsession-pylib'
 import os
 import types
 import gevent
-import cStringIO
+import io
 import copy
 import shutil
 import threading
@@ -77,7 +77,7 @@ def _rewrite_cmd(cmd, params=None):
     cmd = cmd or ''
 
     # find window manager commands
-    if cmd in _X2GO_DESKTOPSESSIONS.keys():
+    if cmd in list(_X2GO_DESKTOPSESSIONS.keys()):
         cmd = _X2GO_DESKTOPSESSIONS[cmd]
 
     if (cmd == 'RDP') and (type(params) == X2GoSessionParams):
@@ -149,9 +149,9 @@ class X2GoSessionParams(object):
                 else: self.session_type = 'R'
             elif cmd == 'XDMCP':
                 self.session_type = 'D'
-            elif cmd in _X2GO_DESKTOPSESSIONS.keys():
+            elif cmd in list(_X2GO_DESKTOPSESSIONS.keys()):
                 self.session_type = 'D'
-            elif os.path.basename(cmd) in _X2GO_DESKTOPSESSIONS.values():
+            elif os.path.basename(cmd) in list(_X2GO_DESKTOPSESSIONS.values()):
                 self.session_type = 'D'
 
         if self.session_type in ("D", "desktop"):
@@ -176,7 +176,7 @@ class X2GoSessionParams(object):
         @type properties_to_be_updated: C{dict}
 
         """
-        for key in properties_to_be_updated.keys():
+        for key in list(properties_to_be_updated.keys()):
             setattr(self, key, properties_to_be_updated[key] or '')
         self.rewrite_session_type()
 
@@ -369,7 +369,7 @@ class X2GoTerminalSession(object):
         self.params.client_encoding = str(client_encoding)
         self.params.server_encoding = str(server_encoding)
 
-        self.params.rootdir = (type(rootdir) is types.StringType) and rootdir or self.sessions_rootdir
+        self.params.rootdir = (type(rootdir) is bytes) and rootdir or self.sessions_rootdir
         self.params.update()
 
         self.profile_name = profile_name
@@ -432,7 +432,7 @@ class X2GoTerminalSession(object):
 
             if self.control_session.get_transport() is not None:
                 try:
-                    for _tunnel in [ _tun[1] for _tun in self.reverse_tunnels[self.session_info.name].values() ]:
+                    for _tunnel in [ _tun[1] for _tun in list(self.reverse_tunnels[self.session_info.name].values()) ]:
                         if _tunnel is not None:
                             _tunnel.__del__()
                 except KeyError:
@@ -459,12 +459,12 @@ class X2GoTerminalSession(object):
         """
         try:
             os.makedirs(rootdir)
-        except OSError, e:
+        except OSError as e:
             if e.errno == 17:
                 # file exists
                 pass
             else:
-                raise OSError, e
+                raise OSError(e)
 
     def _rm_session_dirtree(self):
         """\
@@ -845,7 +845,7 @@ class X2GoTerminalSession(object):
             self.logger('no folder name given...', log.loglevel_WARN)
             return False
 
-        if type(local_path) not in (types.StringType, types.UnicodeType):
+        if type(local_path) not in (bytes, str):
             self.logger('folder name needs to be of type StringType...', log.loglevel_WARN)
             return False
 
@@ -859,7 +859,7 @@ class X2GoTerminalSession(object):
         _auth_rsakey = self.control_session._x2go_session_auth_rsakey
         _host_rsakey = defaults.RSAHostKey
 
-        _tmp_io_object = cStringIO.StringIO()
+        _tmp_io_object = io.StringIO()
         _auth_rsakey.write_private_key(_tmp_io_object)
         _tmp_io_object.write('----BEGIN RSA IDENTITY----')
         _tmp_io_object.write('%s %s' % (_host_rsakey.get_name(),_host_rsakey.get_base64(),))
@@ -1118,7 +1118,7 @@ class X2GoTerminalSession(object):
         else:
             try:
                 os.remove(session_window_file)
-            except OSError,e:
+            except OSError as e:
                 # this is no error in most cases...
                 self.logger('The session window file %s is already gone (we failed to remove it with error: %s). In most cases this can be safely ignored.' % (session_window_file, str(e)), loglevel=log.loglevel_INFO)
 
@@ -1218,7 +1218,7 @@ class X2GoTerminalSession(object):
 
         if cmd in _X2GO_GENERIC_APPLICATIONS:
             return True
-        if cmd in _X2GO_DESKTOPSESSIONS.keys():
+        if cmd in list(_X2GO_DESKTOPSESSIONS.keys()):
             return True
         elif 'XSHAD' in cmd:
             return True
@@ -1296,7 +1296,7 @@ class X2GoTerminalSession(object):
             cmd_line = [ 'PULSE_CLIENTCONFIG=%s/.pulse-client.conf' % self.session_info.remote_container ] + cmd_line
 
         if env:
-            for env_var in env.keys():
+            for env_var in list(env.keys()):
                 cmd_line = [ '%s=%s' % (env_var, env[env_var]) ] + cmd_line
 
         (stdin, stdout, stderr) = self.control_session._x2go_exec_command(cmd_line)
@@ -1387,7 +1387,7 @@ class X2GoTerminalSession(object):
             cmd_line.append("export PULSE_CLIENTCONFIG=%s/.pulse-client.conf && " % self.session_info.remote_container)
 
         if env:
-            for env_var in env.keys():
+            for env_var in list(env.keys()):
                 cmd_line = [ 'export %s=%s && ' % (env_var, env[env_var]) ] + cmd_line
 
         cmd_line.extend(
@@ -1511,7 +1511,7 @@ class X2GoTerminalSession(object):
 
         # if the first line of stdout is a "DEN(Y)" string then we will presume that
         # we tried to use X2Go desktop sharing and the sharing was rejected
-        if "ACCESS DENIED" in _stderr and "XSHAD" in _stderr:
+        if b"ACCESS DENIED" in _stderr and b"XSHAD" in _stderr:
             raise x2go_exceptions.X2GoDesktopSharingDenied('X2Go desktop sharing has been denied by the remote user')
 
         try:
diff --git a/x2go/cache.py b/x2go/cache.py
index 6c8c6ce..b04fca8 100644
--- a/x2go/cache.py
+++ b/x2go/cache.py
@@ -28,8 +28,8 @@ import copy
 import gevent
 
 # Python X2Go modules
-import log
-import x2go_exceptions
+from . import log
+from . import x2go_exceptions
 
 class X2GoListSessionsCache(object):
     """\
@@ -93,7 +93,7 @@ class X2GoListSessionsCache(object):
         the session list cache.
 
         """
-        for profile_name in self.x2go_listsessions_cache.keys():
+        for profile_name in list(self.x2go_listsessions_cache.keys()):
             if profile_name not in self.client_instance.client_connected_profiles(return_profile_names=True):
                 del self.x2go_listsessions_cache[profile_name]
 
@@ -129,7 +129,7 @@ class X2GoListSessionsCache(object):
         self.protected = True
         self.last_listsessions_cache = copy.deepcopy(self.x2go_listsessions_cache)
         control_session = self.client_instance.client_control_session_of_profile_name(profile_name)
-        if not self.x2go_listsessions_cache.has_key(profile_name):
+        if profile_name not in self.x2go_listsessions_cache:
             self.x2go_listsessions_cache[profile_name] = {'sessions': None, 'desktops': None, 'mounts': {}, }
         if update_sessions:
             self._update_sessions(profile_name, control_session)
@@ -156,8 +156,8 @@ class X2GoListSessionsCache(object):
                     if session is not None and session.is_running():
                         if control_session is not None and not control_session.has_session_died():
                             self.x2go_listsessions_cache[profile_name]['mounts'].update(control_session.list_mounts(session_name))
-        except (x2go_exceptions.X2GoControlSessionException, AttributeError), e:
-            if profile_name in self.x2go_listsessions_cache.keys():
+        except (x2go_exceptions.X2GoControlSessionException, AttributeError) as e:
+            if profile_name in list(self.x2go_listsessions_cache.keys()):
                 del self.x2go_listsessions_cache[profile_name]
             self.protected = False
             raise x2go_exceptions.X2GoControlSessionException(str(e))
@@ -180,8 +180,8 @@ class X2GoListSessionsCache(object):
         try:
             if control_session is not None and not control_session.has_session_died():
                 self.x2go_listsessions_cache[profile_name]['desktops'] = control_session.list_desktops()
-        except (x2go_exceptions.X2GoControlSessionException, AttributeError), e:
-            if profile_name in self.x2go_listsessions_cache.keys():
+        except (x2go_exceptions.X2GoControlSessionException, AttributeError) as e:
+            if profile_name in list(self.x2go_listsessions_cache.keys()):
                 del self.x2go_listsessions_cache[profile_name]
             self.protected = False
             raise x2go_exceptions.X2GoControlSessionException(str(e))
@@ -202,8 +202,8 @@ class X2GoListSessionsCache(object):
         try:
             if control_session is not None and not control_session.has_session_died():
                 self.x2go_listsessions_cache[profile_name]['sessions'] = control_session.list_sessions()
-        except (x2go_exceptions.X2GoControlSessionException, AttributeError), e:
-            if profile_name in self.x2go_listsessions_cache.keys():
+        except (x2go_exceptions.X2GoControlSessionException, AttributeError) as e:
+            if profile_name in list(self.x2go_listsessions_cache.keys()):
                 del self.x2go_listsessions_cache[profile_name]
             self.protected = False
             raise x2go_exceptions.X2GoControlSessionException(str(e))
@@ -284,8 +284,8 @@ class X2GoListSessionsCache(object):
                 profile_name = self.client_instance.get_session_profile_name(session_uuid)
             except x2go_exceptions.X2GoSessionRegistryException:
                 raise x2go_exceptions.X2GoSessionCacheException("requested session UUID is not valid anymore")
-        _is_profile_cached = self.x2go_listsessions_cache.has_key(profile_name)
-        _is_cache_type_cached = _is_profile_cached and self.x2go_listsessions_cache[profile_name].has_key(cache_type)
+        _is_profile_cached = profile_name in self.x2go_listsessions_cache
+        _is_cache_type_cached = _is_profile_cached and cache_type in self.x2go_listsessions_cache[profile_name]
         if cache_type is None:
             return _is_profile_cached
         else:
diff --git a/x2go/checkhosts.py b/x2go/checkhosts.py
index 599ce20..0c8d94a 100644
--- a/x2go/checkhosts.py
+++ b/x2go/checkhosts.py
@@ -28,9 +28,9 @@ import paramiko
 import binascii
 
 # Python X2Go modules
-import sshproxy
-import log
-import x2go_exceptions
+from . import sshproxy
+from . import log
+from . import x2go_exceptions
 import random
 import string
 
@@ -284,7 +284,7 @@ def check_ssh_host_key(x2go_sshclient_instance, hostname, port=22):
     except x2go_exceptions.AuthenticationException:
         host_ok = True
         x2go_sshclient_instance.logger('SSH host key verification for host [%s]:%s succeeded. Host is already known to the client\'s Paramiko/SSH sub-system.' % (_hostname, _port), loglevel=log.loglevel_NOTICE)
-    except x2go_exceptions.SSHException, e:
+    except x2go_exceptions.SSHException as e:
         msg = str(e)
         if msg.startswith('Policy has collected host key information on '):
             _hostname = _check_policy.get_hostname().split(':')[0].lstrip('[').rstrip(']')
diff --git a/x2go/cleanup.py b/x2go/cleanup.py
index 7ba17d0..43c1b81 100644
--- a/x2go/cleanup.py
+++ b/x2go/cleanup.py
@@ -27,13 +27,13 @@ import paramiko
 import threading
 
 # Python X2Go modules
-import guardian
-import rforward
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from . import guardian
+from . import rforward
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 
 if _X2GOCLIENT_OS == 'Windows':
-    import xserver
-    import pulseaudio
+    from . import xserver
+    from . import pulseaudio
 
 def x2go_cleanup(e=None, threads=None):
     """\
diff --git a/x2go/client.py b/x2go/client.py
index 925d230..fa3c53e 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -124,31 +124,31 @@ import types
 import os
 
 # Python X2Go modules
-from registry import X2GoSessionRegistry
-from guardian import X2GoSessionGuardian
-from cache import X2GoListSessionsCache
-import x2go_exceptions
-import log
-import utils
+from .registry import X2GoSessionRegistry
+from .guardian import X2GoSessionGuardian
+from .cache import X2GoListSessionsCache
+from . import x2go_exceptions
+from . import log
+from . import utils
 
 # we hide the default values from epydoc (that's why we transform them to _UNDERSCORE variables)
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
-from defaults import LOCAL_HOME as _LOCAL_HOME
-from defaults import CURRENT_LOCAL_USER as _CURRENT_LOCAL_USER
-from defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
-from defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
-from defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
-from defaults import X2GO_SESSIONPROFILES_FILENAME as _X2GO_SESSIONPROFILES_FILENAME
-from defaults import X2GO_SETTINGS_FILENAME as _X2GO_SETTINGS_FILENAME
-from defaults import X2GO_PRINTING_FILENAME as _X2GO_PRINTING_FILENAME
-from defaults import X2GO_XCONFIG_FILENAME as _X2GO_XCONFIG_FILENAME
-from defaults import PUBAPP_MAX_NO_SUBMENUS as _PUBAPP_MAX_NO_SUBMENUS
-
-from defaults import BACKENDS as _BACKENDS
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import LOCAL_HOME as _LOCAL_HOME
+from .defaults import CURRENT_LOCAL_USER as _CURRENT_LOCAL_USER
+from .defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
+from .defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
+from .defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
+from .defaults import X2GO_SESSIONPROFILES_FILENAME as _X2GO_SESSIONPROFILES_FILENAME
+from .defaults import X2GO_SETTINGS_FILENAME as _X2GO_SETTINGS_FILENAME
+from .defaults import X2GO_PRINTING_FILENAME as _X2GO_PRINTING_FILENAME
+from .defaults import X2GO_XCONFIG_FILENAME as _X2GO_XCONFIG_FILENAME
+from .defaults import PUBAPP_MAX_NO_SUBMENUS as _PUBAPP_MAX_NO_SUBMENUS
+
+from .defaults import BACKENDS as _BACKENDS
 
 if _X2GOCLIENT_OS == 'Windows':
-    from xserver import X2GoClientXConfig, X2GoXServer
-    from pulseaudio import X2GoPulseAudio
+    from .xserver import X2GoClientXConfig, X2GoXServer
+    from .pulseaudio import X2GoPulseAudio
 
 
 class X2GoClient(object):
@@ -314,12 +314,12 @@ class X2GoClient(object):
             else:
 
                 _last_display = None
-                if  type(start_xserver) is types.BooleanType:
+                if  type(start_xserver) is bool:
                     p_xs_name = self.client_xconfig.preferred_xserver_names[0]
                     _last_display = self.client_xconfig.get_xserver_config(p_xs_name)['last_display']
                     _new_display = self.client_xconfig.detect_unused_xdisplay_port(p_xs_name)
                     p_xs = (p_xs_name, self.client_xconfig.get_xserver_config(p_xs_name))
-                elif type(start_xserver) is types.StringType:
+                elif type(start_xserver) is bytes:
                     _last_display = self.client_xconfig.get_xserver_config(start_xserver)['last_display']
                     _new_display = self.client_xconfig.detect_unused_xdisplay_port(start_xserver)
                     p_xs = (start_xserver, self.client_xconfig.get_xserver_config(start_xserver))
@@ -622,7 +622,7 @@ class X2GoClient(object):
         @type subsystem: C{str}
 
         """
-        if type(subsystem) in (types.StringType, types.UnicodeType):
+        if type(subsystem) in (bytes, str):
             _subsystem = '(%s) ' % subsystem
         else:
             _subsystem = ''
@@ -950,7 +950,7 @@ class X2GoClient(object):
             _profile_id = None
 
         # test if session_name has already been registered. If yes, return it immediately.
-        if type(session_name) is types.StringType:
+        if type(session_name) is bytes:
             _retval = self.get_session_of_session_name(session_name, return_object=return_object, match_profile_name=profile_name)
             if _retval is not None:
                 return _retval
@@ -967,8 +967,8 @@ class X2GoClient(object):
             del _params['profile_name']
 
             # override any available session parameter passed to this method
-            for k in _params.keys():
-                if k in kwargs.keys():
+            for k in list(_params.keys()):
+                if k in list(kwargs.keys()):
                     _params[k] = kwargs[k]
 
             _pkey = None
@@ -976,7 +976,7 @@ class X2GoClient(object):
                 server = self.session_profiles.get_server_hostname(_profile_id)
                 _params['port'] = self.session_profiles.get_server_port(_profile_id)
                 _pkey = self.session_profiles.get_pkey_object(_profile_id)
-            except x2go_exceptions.X2GoBrokerConnectionException, e:
+            except x2go_exceptions.X2GoBrokerConnectionException as e:
                 _profile_name = self.to_profile_name(_profile_id)
                 self.HOOK_broker_connection_exception(_profile_name)
                 if not self.HOOK_broker_ignore_connection_problems(_profile_name, is_profile_connected=self.is_profile_connected(_profile_name)):
@@ -2010,7 +2010,7 @@ class X2GoClient(object):
             if check_list_mounts:
                 _mounts = self.list_mounts_by_profile_name(profile_name)
                 mounts = []
-                for mount_list in _mounts.values():
+                for mount_list in list(_mounts.values()):
                     mounts.extend(mount_list)
 
             return self.session_registry(session_uuid).get_shared_folders(check_list_mounts=check_list_mounts, mounts=mounts)
@@ -2480,7 +2480,7 @@ class X2GoClient(object):
         """
         if self._X2GoClient__is_session_connected(session_uuid):
             session_list = self._X2GoClient__list_sessions(session_uuid)
-            return [ key for key in session_list.keys() if session_list[key].status == 'R' ]
+            return [ key for key in list(session_list.keys()) if session_list[key].status == 'R' ]
         else:
             raise x2go_exceptions.X2GoClientException('X2Go session with UUID %s is not connected' % session_uuid)
     __server_running_sessions = server_running_sessions
@@ -2527,7 +2527,7 @@ class X2GoClient(object):
         """
         if self._X2GoClient__is_session_connected(session_uuid):
             session_list = self._X2GoClient__list_sessions(session_uuid)
-            return [ key for key in session_list.keys() if session_list[key].status == 'S' ]
+            return [ key for key in list(session_list.keys()) if session_list[key].status == 'S' ]
         else:
             raise x2go_exceptions.X2GoClientException('X2Go session with UUID %s is not connected' % session_uuid)
     __server_suspended_sessions = server_suspended_sessions
@@ -3174,7 +3174,7 @@ class X2GoClient(object):
                                                       )
         try:
             self.session_registry.register_available_server_sessions(profile_name, session_list=session_list, re_register=re_register, skip_pubapp_sessions=skip_pubapp_sessions)
-        except x2go_exceptions.X2GoControlSessionException, e:
+        except x2go_exceptions.X2GoControlSessionException as e:
             c_sessions = self.client_connected_sessions_of_profile_name(profile_name, return_objects=True)
             if len(c_sessions) and c_sessions[0].connected: self.HOOK_on_control_session_death(profile_name)
             self.disconnect_profile(profile_name)
diff --git a/x2go/defaults.py b/x2go/defaults.py
index aef035f..3d03481 100644
--- a/x2go/defaults.py
+++ b/x2go/defaults.py
@@ -91,7 +91,7 @@ elif X2GOCLIENT_OS == "Mac":
 
 else:
     import exceptions
-    class OSNotSupportedException(exceptions.StandardError): pass
+    class OSNotSupportedException(exceptions.Exception): pass
     raise OSNotSupportedException('Platform %s is not supported' % platform.system())
 
 ##
diff --git a/x2go/forward.py b/x2go/forward.py
index 9f63140..090bfd1 100644
--- a/x2go/forward.py
+++ b/x2go/forward.py
@@ -31,8 +31,8 @@ from gevent import select, socket
 from gevent.server import StreamServer
 
 # Python X2Go modules
-import log
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from . import log
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 
 class X2GoFwServer(StreamServer):
     """\
@@ -123,7 +123,7 @@ class X2GoFwServer(StreamServer):
                                                             self.fw_socket.getpeername())
                 chan_peername = self.chan.getpeername()
                 _success = True
-            except Exception, e:
+            except Exception as e:
                 if self.keepalive:
                     self.logger('incoming request to %s:%d failed on attempt %d of %d: %s' % (self.chain_host,
                                                                                               self.chain_port,
diff --git a/x2go/gevent_subprocess.py b/x2go/gevent_subprocess.py
index 5ef14e3..8e823df 100644
--- a/x2go/gevent_subprocess.py
+++ b/x2go/gevent_subprocess.py
@@ -48,7 +48,6 @@ from gevent import socket, select, hub
 
 # identical to original
 CalledProcessError = _subprocess.CalledProcessError
-MAXFD = _subprocess.MAXFD
 PIPE = _subprocess.PIPE
 STDOUT = _subprocess.STDOUT
 call = _subprocess.call
@@ -81,7 +80,7 @@ class Popen(object):
                 try:
                     # f.write() doesn't return anything, so use os.write.
                     bytes_written += os.write(f.fileno(), input[bytes_written:])
-                except IOError, ex:
+                except IOError as ex:
                     if ex[0] != errno.EAGAIN:
                         raise
                     sys.exc_clear()
@@ -98,7 +97,7 @@ class Popen(object):
                 if not chunk:
                     break
                 chunks.append(chunk)
-            except IOError, ex:
+            except IOError as ex:
                 if ex[0] != errno.EAGAIN:
                     raise
                 sys.exc_clear()
@@ -149,7 +148,7 @@ class Popen(object):
         while read_set or write_set:
             try:
                 rlist, wlist, xlist = select.select(read_set, write_set, [])
-            except select.error, e:
+            except select.error as e:
                 if e.args[0] == errno.EINTR:
                     continue
                 raise
@@ -205,7 +204,7 @@ class Popen(object):
                 if status >= 0:
                     return status
                 hub.sleep(check_interval)
-        except OSError, e:
+        except OSError as e:
             if e.errno == errno.ECHILD:
                 # no child process, this happens if the child process
                 # already died and has been cleaned up
diff --git a/x2go/guardian.py b/x2go/guardian.py
index b9683f8..73f3dac 100644
--- a/x2go/guardian.py
+++ b/x2go/guardian.py
@@ -31,8 +31,8 @@ import threading
 import copy
 
 # Python X2Go modules
-from cleanup import x2go_cleanup
-import log
+from .cleanup import x2go_cleanup
+from . import log
 
 class X2GoSessionGuardian(threading.Thread):
     """\
@@ -125,7 +125,7 @@ class X2GoSessionGuardian(threading.Thread):
 
         self.logger('X2Go session guardian thread waking up after %s seconds' % seconds, loglevel=log.loglevel_DEBUG)
 
-        for session_uuid in self.client_instance.session_registry.keys():
+        for session_uuid in list(self.client_instance.session_registry.keys()):
             session_summary = self.client_instance.get_session_summary(session_uuid)
             self.logger('calling session cleanup on profile %s for terminal session: %s' % (session_summary['profile_name'], session_summary['session_name']), loglevel=log.loglevel_DEBUG)
             x2go_cleanup(threads=session_summary['active_threads'])
diff --git a/x2go/inifiles.py b/x2go/inifiles.py
index 9bb7b3b..6b9c268 100644
--- a/x2go/inifiles.py
+++ b/x2go/inifiles.py
@@ -31,15 +31,15 @@ __NAME__ = 'x2goinifiles-pylib'
 
 # modules
 import os
-import ConfigParser
+import configparser
 import types
-import cStringIO
+import io
 import copy
 
 # Python X2Go modules
-from defaults import LOCAL_HOME as _current_home
-import log
-import utils
+from .defaults import LOCAL_HOME as _current_home
+from . import log
+from . import utils
 
 class X2GoIniFile(object):
     """
@@ -93,7 +93,7 @@ class X2GoIniFile(object):
         # here as we do not want to run into name conflicts between
         # X2Go ini file options and method / property names in
         # SafeConfigParser... This is a pre-cautious approach...
-        self.iniConfig = ConfigParser.SafeConfigParser()
+        self.iniConfig = configparser.SafeConfigParser()
         self.iniConfig.optionxform = str
 
         _create_file = False
@@ -154,11 +154,9 @@ class X2GoIniFile(object):
         @type value: C{str}, C{list}, C{booAl}, ...
 
         """
-        if type(value) == type(u''):
-            value = value.encode(utils.get_encoding())
-        if type(value) is types.BooleanType:
+        if type(value) is bool:
             self.iniConfig.set(section, key, str(int(value)))
-        elif type(value) in (types.ListType, types.TupleType):
+        elif type(value) in (list, tuple):
             self.iniConfig.set(section, key, ", ".join(value))
         else:
             self.iniConfig.set(section, key, str(value))
@@ -171,8 +169,8 @@ class X2GoIniFile(object):
         method.
 
         """
-        for section, sectionvalue in self.defaultValues.items():
-            for key, value in sectionvalue.items():
+        for section, sectionvalue in list(self.defaultValues.items()):
+            for key, value in list(sectionvalue.items()):
                 if self.iniConfig.has_option(section, key): continue
                 if not self.iniConfig.has_section(section):
                     self.iniConfig.add_section(section)
@@ -215,8 +213,8 @@ class X2GoIniFile(object):
                 fd.close()
                 self._write_user_config = False
                 return True
-            except Exception, e:
-                print e
+            except Exception as e:
+                print(e)
         return False
     __write = write
 
@@ -252,11 +250,11 @@ class X2GoIniFile(object):
         if key_type is None:
             key_type = self.get_type(section, key)
         if self.iniConfig.has_option(section, key):
-            if key_type is types.BooleanType:
+            if key_type is bool:
                 return self.iniConfig.getboolean(section, key)
-            elif key_type is types.IntType:
+            elif key_type is int:
                 return self.iniConfig.getint(section, key)
-            elif key_type is types.ListType:
+            elif key_type is list:
                 _val = self.iniConfig.get(section, key)
                 _val = _val.strip()
                 if _val.startswith('[') and _val.endswith(']'):
@@ -268,7 +266,7 @@ class X2GoIniFile(object):
                 return _val
             else:
                 _val = self.iniConfig.get(section, key)
-                return _val.decode(utils.get_encoding())
+                return _val
     get = get_value
     __call__ = get_value
 
@@ -278,7 +276,7 @@ class X2GoIniFile(object):
         Returns a printable configuration file as a multi-line string.
 
         """
-        stdout = cStringIO.StringIO()
+        stdout = io.StringIO()
         self.iniConfig.write(stdout)
         _ret_val = stdout.getvalue()
         stdout.close()
diff --git a/x2go/log.py b/x2go/log.py
index fd7d45f..20bc3b0 100644
--- a/x2go/log.py
+++ b/x2go/log.py
@@ -42,7 +42,7 @@ Default loglevel of X2GoLogger objects is: NOTICE & WARN & ERROR
 """
 
 # Python X2Go modules
-import utils
+from . import utils
 
 class X2GoLogger(object):
     """\
@@ -98,9 +98,9 @@ class X2GoLogger(object):
             msg = msg.encode(utils.get_encoding())
 
             if self.tag is not None:
-                self.destination.write('%s[%s] (%s) %s: %s\n' % (self.name, self.progpid, tag, self._loglevel_NAMES[loglevel].upper(), msg))
+                self.destination.write('%s[%s] (%s) %s: %s\n' % (self.name, self.progpid, tag, self._loglevel_NAMES[loglevel].upper(), msg.decode()))
             else:
-                self.destination.write('%s[%s] %s: %s\n' % (self.name, self.progpid, self._loglevel_NAMES[loglevel].upper(), msg))
+                self.destination.write('%s[%s] %s: %s\n' % (self.name, self.progpid, self._loglevel_NAMES[loglevel].upper(), msg.decode()))
     __call__ = message
 
     def get_loglevel(self):
@@ -123,7 +123,7 @@ class X2GoLogger(object):
         """
         if type(loglevel_name) is types.IntegerType:
             self.loglevel = loglevel_name
-        elif type(loglevel_name) is types.StringType and loglevel_name in self._loglevel_NAMES.values():
+        elif type(loglevel_name) is bytes and loglevel_name in list(self._loglevel_NAMES.values()):
             _method = getattr(self, 'self.set_loglevel_%s' % loglevel_name)
             _method()
         else:
diff --git a/x2go/mimebox.py b/x2go/mimebox.py
index 92bce8e..6705642 100644
--- a/x2go/mimebox.py
+++ b/x2go/mimebox.py
@@ -36,10 +36,10 @@ import threading
 import gevent
 
 # Python X2Go modules
-import defaults
-import utils
-import log
-import mimeboxactions
+from . import defaults
+from . import utils
+from . import log
+from . import mimeboxactions
 
 
 class X2GoMIMEboxQueue(threading.Thread):
@@ -95,7 +95,7 @@ class X2GoMIMEboxQueue(threading.Thread):
 
         if mimebox_action is None:
             mimebox_action = mimeboxactions.X2GoMIMEboxActionOPEN(client_instance=self.client_instance, logger=self.logger)
-        elif type(mimebox_action) in (types.StringType, types.UnicodeType):
+        elif type(mimebox_action) in (bytes, str):
             mimebox_action = self.set_mimebox_action(mimebox_action, client_instance=self.client_instance, logger=self.logger)
         else:
             # hope it's already an instance...
@@ -151,7 +151,7 @@ class X2GoMIMEboxQueue(threading.Thread):
                 mimebox_jobs.extend([ dj for dj in l if dj.upper().endswith(_ext.upper()) ])
             else:
                 mimebox_jobs = l
-            return [ dj for dj in mimebox_jobs if dj not in self.active_jobs.keys() ]
+            return [ dj for dj in mimebox_jobs if dj not in list(self.active_jobs.keys()) ]
         else:
             return []
 
@@ -167,10 +167,10 @@ class X2GoMIMEboxQueue(threading.Thread):
         @type kwargs: C{dict}
 
         """
-        if mimebox_action in defaults.X2GO_MIMEBOX_ACTIONS.keys():
+        if mimebox_action in list(defaults.X2GO_MIMEBOX_ACTIONS.keys()):
             mimebox_action = defaults.X2GO_MIMEBOX_ACTIONS[mimebox_action]
 
-        if mimebox_action in defaults.X2GO_MIMEBOX_ACTIONS.values():
+        if mimebox_action in list(defaults.X2GO_MIMEBOX_ACTIONS.values()):
             self.mimebox_action = eval ('mimeboxactions.%s(**kwargs)' % mimebox_action)
 
     def run(self):
diff --git a/x2go/mimeboxactions.py b/x2go/mimeboxactions.py
index 7d3d2ca..cc03c08 100644
--- a/x2go/mimeboxactions.py
+++ b/x2go/mimeboxactions.py
@@ -29,18 +29,18 @@ import os
 import copy
 import time
 
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 if _X2GOCLIENT_OS in ("Windows"):
     import subprocess
     import win32api
 else:
-    import gevent_subprocess as subprocess
-    import x2go_exceptions
+    from . import gevent_subprocess as subprocess
+    from . import x2go_exceptions
     WindowsErrror = x2go_exceptions.WindowsError
 
 # Python X2Go modules
-import log
-import x2go_exceptions
+from . import log
+from . import x2go_exceptions
 
 _MIMEBOX_ENV = os.environ.copy()
 
@@ -162,7 +162,7 @@ class X2GoMIMEboxActionOPEN(X2GoMIMEboxAction):
             self.logger('opening incoming MIME box file with Python\'s os.startfile() command: %s' % mimebox_file, loglevel=log.loglevel_DEBUG)
             try:
                 os.startfile(os.path.join(mimebox_dir, mimebox_file))
-            except WindowsError, win_err:
+            except WindowsError as win_err:
                 if self.client_instance:
                     self.client_instance.HOOK_mimeboxaction_error(mimebox_file,
                                                                   profile_name=self.profile_name,
diff --git a/x2go/printactions.py b/x2go/printactions.py
index b483df8..c730eba 100644
--- a/x2go/printactions.py
+++ b/x2go/printactions.py
@@ -34,22 +34,22 @@ import copy
 import time
 import gevent
 
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 if _X2GOCLIENT_OS in ("Windows"):
     import subprocess
     import win32api
     import win32print
 else:
-    import gevent_subprocess as subprocess
-    import x2go_exceptions
+    from . import gevent_subprocess as subprocess
+    from . import x2go_exceptions
     WindowsError = x2go_exceptions.WindowsError
 
 # Python X2Go modules
-import log
-import defaults
+from . import log
+from . import defaults
 # we hide the default values from epydoc (that's why we transform them to _UNDERSCORE variables)
-import utils
-import x2go_exceptions
+from . import utils
+from . import x2go_exceptions
 
 _PRINT_ENV = os.environ.copy()
 
@@ -208,7 +208,7 @@ class X2GoPrintActionPDFVIEW(X2GoPrintAction):
             self.logger('viewing incoming job in PDF viewer with Python\'s os.startfile(command): %s' % pdf_file, loglevel=log.loglevel_DEBUG)
             try:
                 gevent.spawn(os.startfile, pdf_file)
-            except WindowsError, win_err:
+            except WindowsError as win_err:
                 if self.client_instance:
                     self.client_instance.HOOK_printaction_error(pdf_file,
                                                                 profile_name=self.profile_name,
@@ -225,7 +225,7 @@ class X2GoPrintActionPDFVIEW(X2GoPrintAction):
             self.logger('viewing incoming PDF with command: %s' % ' '.join(cmd_line), loglevel=log.loglevel_DEBUG)
             try:
                 subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=_PRINT_ENV)
-            except OSError, e:
+            except OSError as e:
                 if e.errno == 2:
                     cmd_line = [ defaults.DEFAULT_PDFVIEW_CMD, _hr_filename ]
                     subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=_PRINT_ENV)
@@ -272,7 +272,7 @@ class X2GoPrintActionPDFSAVE(X2GoPrintAction):
 
         self.logger('Save location for incoming PDFs is: %s' % self.save_to_folder, loglevel=log.loglevel_DEBUG)
         if not os.path.exists(self.save_to_folder):
-            os.makedirs(self.save_to_folder, mode=0755)
+            os.makedirs(self.save_to_folder, mode=0o755)
 
     def _do_print(self, pdf_file, job_title, spool_dir):
         """\
@@ -376,7 +376,7 @@ class X2GoPrintActionPRINT(X2GoPrintAction):
                     )
                     # give the win32api some time to find our printer...
                     time.sleep(10)
-                except win32api.error, e:
+                except win32api.error as e:
                     if self.client_instance:
                         self.client_instance.HOOK_printaction_error(filename=_hr_filename, printer=_printer, err_msg=e.message, profile_name=self.profile_name, session_name=self.session_name)
                     else:
diff --git a/x2go/printqueue.py b/x2go/printqueue.py
index 3404c58..b0c194a 100644
--- a/x2go/printqueue.py
+++ b/x2go/printqueue.py
@@ -34,12 +34,12 @@ import threading
 import gevent
 
 # Python X2Go modules
-import defaults
-import utils
-import log
+from . import defaults
+from . import utils
+from . import log
 
-from defaults import X2GO_PRINTING_FILENAME as _X2GO_PRINTING_FILENAME
-from defaults import BACKENDS as _BACKENDS
+from .defaults import X2GO_PRINTING_FILENAME as _X2GO_PRINTING_FILENAME
+from .defaults import BACKENDS as _BACKENDS
 
 class X2GoPrintQueue(threading.Thread):
     """\
@@ -157,7 +157,7 @@ class X2GoPrintQueue(threading.Thread):
                     job_title = 'X2Go Print Job'
                 _job_file_handle.close()
                 jobs.append((_job_file, pdf_filename, job_title))
-            return [ j for j in jobs if j[1] not in self.active_jobs.keys() ]
+            return [ j for j in jobs if j[1] not in list(self.active_jobs.keys()) ]
         else:
             return []
 
@@ -176,10 +176,10 @@ class X2GoPrintQueue(threading.Thread):
         @type kwargs: C{dict}
 
         """
-        if print_action in defaults.X2GO_PRINT_ACTIONS.keys():
+        if print_action in list(defaults.X2GO_PRINT_ACTIONS.keys()):
             print_action = defaults.X2GO_PRINT_ACTIONS[print_action]
 
-        if print_action in defaults.X2GO_PRINT_ACTIONS.values():
+        if print_action in list(defaults.X2GO_PRINT_ACTIONS.values()):
             self.print_action = eval ('printactions.%s(**kwargs)' % print_action)
 
     def run(self):
diff --git a/x2go/pulseaudio.py b/x2go/pulseaudio.py
index 7426f45..eb56c25 100644
--- a/x2go/pulseaudio.py
+++ b/x2go/pulseaudio.py
@@ -27,7 +27,7 @@ X2GoPulseAudio class - a Pulseaudio daemon guardian thread.
 
 __NAME__ = 'x2gopulseaudio-pylib'
 
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 if _X2GOCLIENT_OS == 'Windows':
     import win32process
     import win32con
@@ -41,13 +41,13 @@ import gevent
 import copy
 import socket
 
-from defaults import LOCAL_HOME as _LOCAL_HOME
+from .defaults import LOCAL_HOME as _LOCAL_HOME
 
 # Python X2Go modules
-import log
+from . import log
 
 import exceptions
-class OSNotSupportedException(exceptions.StandardError): pass
+class OSNotSupportedException(exceptions.Exception): pass
 """ Exception denoting that this operating system is not supported. """
 
 class X2GoPulseAudio(threading.Thread):
@@ -147,7 +147,7 @@ class X2GoPulseAudio(threading.Thread):
                                               )
         _is_alive = ( rc != win32event.WAIT_OBJECT_0 )
         if self.client_instance and not _is_alive:
-            if os.environ.has_key('CLIENTNAME'):
+            if 'CLIENTNAME' in os.environ:
                 self.client_instance.HOOK_pulseaudio_not_supported_in_RDPsession()
             else:
                 self.client_instance.HOOK_pulseaudio_server_startup_failed()
diff --git a/x2go/registry.py b/x2go/registry.py
index 3add0a6..6dde80d 100644
--- a/x2go/registry.py
+++ b/x2go/registry.py
@@ -31,18 +31,18 @@ import threading
 import re
 
 # Python X2Go modules
-import log
-import utils
-import session
-import x2go_exceptions
+from . import log
+from . import utils
+from . import session
+from . import x2go_exceptions
 
-from defaults import LOCAL_HOME as _LOCAL_HOME
-from defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
-from defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
-from defaults import X2GO_SESSIONPROFILE_DEFAULTS as _X2GO_SESSIONPROFILE_DEFAULTS
-from defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
+from .defaults import LOCAL_HOME as _LOCAL_HOME
+from .defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
+from .defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
+from .defaults import X2GO_SESSIONPROFILE_DEFAULTS as _X2GO_SESSIONPROFILE_DEFAULTS
+from .defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
 
-from defaults import BACKENDS as _BACKENDS
+from .defaults import BACKENDS as _BACKENDS
 
 
 class X2GoSessionRegistry(object):
@@ -87,7 +87,7 @@ class X2GoSessionRegistry(object):
         @rtype: C{list}
 
         """
-        return self.registry.keys()
+        return list(self.registry.keys())
 
     def __repr__(self):
         result = 'X2GoSessionRegistry('
@@ -299,7 +299,7 @@ class X2GoSessionRegistry(object):
                     if self(_session_uuid).terminal_session:
 
                         # declare as master session if appropriate
-                        if _profile_name not in self.master_sessions.keys():
+                        if _profile_name not in list(self.master_sessions.keys()):
                             self.master_sessions[_profile_name] = self(_session_uuid)
                             self(_session_uuid).set_master_session()
 
@@ -327,7 +327,7 @@ class X2GoSessionRegistry(object):
             elif _last_status['connected'] and (not _last_status['suspended'] and _current_status['suspended']) and not _current_status['faulty'] and _session_name:
 
                 # unregister as master session
-                if _profile_name in self.master_sessions.keys():
+                if _profile_name in list(self.master_sessions.keys()):
                     if self.master_sessions[_profile_name] == self(_session_uuid):
 
                         self(_session_uuid).unset_master_session()
@@ -340,7 +340,7 @@ class X2GoSessionRegistry(object):
             elif _last_status['connected'] and (not _last_status['terminated'] and _current_status['terminated']) and not _current_status['faulty'] and _session_name:
 
                 # unregister as master session
-                if _profile_name in self.master_sessions.keys():
+                if _profile_name in list(self.master_sessions.keys()):
                     if self.master_sessions[_profile_name] == self(_session_uuid):
 
                         self(_session_uuid).unset_master_session()
@@ -356,7 +356,7 @@ class X2GoSessionRegistry(object):
                     self.forget(_session_uuid)
 
         # detect master sessions for connected profiles that have lost (suspend/terminate) their master session or never had a master session
-        for _profile_name in [ p for p in self.connected_profiles(return_profile_names=True) if p not in self.master_sessions.keys() ]:
+        for _profile_name in [ p for p in self.connected_profiles(return_profile_names=True) if p not in list(self.master_sessions.keys()) ]:
             _running_associated_sessions = [ _s for _s in self.running_sessions_of_profile_name(_profile_name, return_objects=True) if _s.is_associated() ]
             if _running_associated_sessions:
                 for _r_a_s in _running_associated_sessions:
@@ -364,7 +364,7 @@ class X2GoSessionRegistry(object):
                         self.master_sessions[_profile_name] = _r_a_s
                         _r_a_s.set_master_session(wait=1)
                         break
-                if not self.master_sessions.has_key(_profile_name):
+                if _profile_name not in self.master_sessions:
                     _pubapp_associated_sessions = self.pubapp_sessions_of_profile_name(_profile_name, return_objects=True)
                     if _pubapp_associated_sessions:
                         self.master_sessions[_profile_name] = _pubapp_associated_sessions[0]
@@ -415,7 +415,7 @@ class X2GoSessionRegistry(object):
             # make sure the session registry gets updated before registering new session
             # (if the server name has changed, this will kick out obsolete X2GoSessions)
             self.update_status(profile_name=profile_name, session_list=session_list, force_update=True)
-            for session_name in session_list.keys():
+            for session_name in list(session_list.keys()):
                 if (session_name not in _session_names and not self._skip_auto_registration) or re_register:
                     server = _ctrl_session.get_server_hostname()
                     profile_id = _ctrl_session.get_profile_id()
@@ -514,13 +514,13 @@ class X2GoSessionRegistry(object):
         @rtype: C{str}
 
         """
-        if profile_id not in self._profile_locks.keys():
+        if profile_id not in list(self._profile_locks.keys()):
             self._profile_locks[profile_id] = threading.Lock()
 
         self._profile_locks[profile_id].acquire()
 
         control_session = None
-        if profile_id in self.control_sessions.keys():
+        if profile_id in list(self.control_sessions.keys()):
             control_session = self.control_sessions[profile_id]
 
         try:
@@ -529,14 +529,14 @@ class X2GoSessionRegistry(object):
         except x2go_exceptions.X2GoProfileException:
             _params = utils._convert_SessionProfileOptions_2_SessionParams(_X2GO_SESSIONPROFILE_DEFAULTS)
 
-        for _k in _params.keys():
-            if _k in kwargs.keys():
+        for _k in list(_params.keys()):
+            if _k in list(kwargs.keys()):
                 _params[_k] = kwargs[_k]
 
         # allow injection of PKey objects (Paramiko's private SSH keys)
-        if kwargs.has_key('pkey'):
+        if 'pkey' in kwargs:
             _params['pkey'] = kwargs['pkey']
-        if kwargs.has_key('sshproxy_pkey'):
+        if 'sshproxy_pkey' in kwargs:
             _params['sshproxy_pkey'] = kwargs['sshproxy_pkey']
 
         # when starting a new session, we will try to use unused registered virgin sessions
@@ -590,7 +590,7 @@ class X2GoSessionRegistry(object):
         self.logger('registering X2Go session with UUID %s' % session_uuid, log.loglevel_DEBUG)
 
         self.registry[session_uuid] = s
-        if profile_id not in self.control_sessions.keys():
+        if profile_id not in list(self.control_sessions.keys()):
             self.control_sessions[profile_id] = s.get_control_session()
 
         # make sure a new session is a non-master session unless promoted in update_status method
@@ -652,11 +652,11 @@ class X2GoSessionRegistry(object):
 
     def _sessionsWithState(self, state, return_objects=True, return_profile_names=False, return_profile_ids=False, return_session_names=False):
         if state == 'associated':
-            sessions = [ ts for ts in self.registry.values() if ts.has_terminal_session() ]
+            sessions = [ ts for ts in list(self.registry.values()) if ts.has_terminal_session() ]
         elif state == 'registered':
-            sessions = [ ts for ts in self.registry.values() ]
+            sessions = [ ts for ts in list(self.registry.values()) ]
         else:
-            sessions = [ ts for ts in self.registry.values() if eval('ts.%s' % state) ]
+            sessions = [ ts for ts in list(self.registry.values()) if eval('ts.%s' % state) ]
         if return_profile_names:
             profile_names = []
             for this_session in sessions:
@@ -1041,7 +1041,7 @@ class X2GoSessionRegistry(object):
         Equals a list of all currently connected control sessions.
 
         """
-        return [ c for c in self.control_sessions.values() if c.is_connected() ]
+        return [ c for c in list(self.control_sessions.values()) if c.is_connected() ]
 
     def connected_profiles(self, use_paramiko=False, return_profile_ids=True, return_profile_names=False):
         """\
@@ -1055,7 +1055,7 @@ class X2GoSessionRegistry(object):
 
         """
         if use_paramiko:
-            return [ p for p in self.control_sessions.keys() if self.control_sessions[p].is_connected() ]
+            return [ p for p in list(self.control_sessions.keys()) if self.control_sessions[p].is_connected() ]
         else:
             return self.connected_sessions(return_profile_ids=return_profile_ids, return_profile_names=return_profile_names)
 
@@ -1077,7 +1077,7 @@ class X2GoSessionRegistry(object):
         if profile_name not in self.connected_profiles(return_profile_names=True):
             return None
 
-        if profile_name not in self.master_sessions.keys() or self.master_sessions[profile_name] is None:
+        if profile_name not in list(self.master_sessions.keys()) or self.master_sessions[profile_name] is None:
             return None
 
         _session = self.master_sessions[profile_name]
diff --git a/x2go/rforward.py b/x2go/rforward.py
index 6e0d864..77146f5 100644
--- a/x2go/rforward.py
+++ b/x2go/rforward.py
@@ -33,10 +33,10 @@ import paramiko
 from gevent import select, socket, Timeout
 
 # Python X2Go modules
-import log
+from . import log
 
 
-def x2go_transport_tcp_handler(chan, (origin_addr, origin_port), (server_addr, server_port)):
+def x2go_transport_tcp_handler(chan, xxx_todo_changeme, xxx_todo_changeme1):
     """\
     An X2Go customized TCP handler for the Paramiko/SSH C{Transport()} class.
 
@@ -53,13 +53,15 @@ def x2go_transport_tcp_handler(chan, (origin_addr, origin_port), (server_addr, s
     started. This L{X2GoRevFwChannelThread} then takes care of the new channel's incoming data stream.
 
     """
+    (origin_addr, origin_port) = xxx_todo_changeme
+    (server_addr, server_port) = xxx_todo_changeme1
     transport = chan.get_transport()
     transport._queue_incoming_channel(chan)
     rev_tuns = transport.reverse_tunnels
 
-    for session_name in rev_tuns.keys():
+    for session_name in list(rev_tuns.keys()):
 
-        if int(server_port) in [ int(tunnel[0]) for tunnel in rev_tuns[session_name].values() ]:
+        if int(server_port) in [ int(tunnel[0]) for tunnel in list(rev_tuns[session_name].values()) ]:
 
             if rev_tuns[session_name]['snd'] is not None and int(server_port) == int(rev_tuns[session_name]['snd'][0]):
                 rev_tuns[session_name]['snd'][1].notify()
@@ -210,7 +212,7 @@ class X2GoRevFwTunnel(threading.Thread):
             gevent.sleep(1)
             try:
                 self._requested_port = self.ssh_transport.request_port_forward('127.0.0.1', self.server_port, handler=x2go_transport_tcp_handler)
-            except paramiko.SSHException, e:
+            except paramiko.SSHException as e:
                 if self.session_instance:
                     self.session_instance.HOOK_rforward_request_denied(server_port=self.server_port)
                 else:
@@ -305,7 +307,7 @@ def x2go_rev_forward_channel_handler(chan=None, addr='', port=0, parent_thread=N
 
     try:
         fw_socket.connect((addr, port))
-    except Exception, e:
+    except Exception as e:
         logger('Reverse forwarding request to %s:%d failed: %r' % (addr, port, e), loglevel=log.loglevel_INFO)
         return
 
@@ -325,7 +327,7 @@ def x2go_rev_forward_channel_handler(chan=None, addr='', port=0, parent_thread=N
                 if len(data) == 0:
                     break
                 fw_socket.send(data)
-        except socket.error, e:
+        except socket.error as e:
             logger('Reverse tunnel %s encoutered socket error: %s' % (chan, str(e)), loglevel=log.loglevel_WARN)
 
     chan.close()
diff --git a/x2go/session.py b/x2go/session.py
index 0500470..c858fc9 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -65,21 +65,21 @@ import base64
 import paramiko
 
 # Python X2Go modules
-import defaults
-import log
-import utils
-import session
-import x2go_exceptions
+from . import defaults
+from . import log
+from . import utils
+from . import session
+from . import x2go_exceptions
 
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
-from defaults import LOCAL_HOME as _LOCAL_HOME
-from defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
-from defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
-from defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import LOCAL_HOME as _LOCAL_HOME
+from .defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
+from .defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
+from .defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR
 
-from defaults import BACKENDS as _BACKENDS
+from .defaults import BACKENDS as _BACKENDS
 
-from defaults import SUPPORTED_SOUND, SUPPORTED_PRINTING, SUPPORTED_FOLDERSHARING, SUPPORTED_MIMEBOX, SUPPORTED_TELEKINESIS
+from .defaults import SUPPORTED_SOUND, SUPPORTED_PRINTING, SUPPORTED_FOLDERSHARING, SUPPORTED_MIMEBOX, SUPPORTED_TELEKINESIS
 
 _X2GO_SESSION_PARAMS = ('use_sshproxy', 'sshproxy_reuse_authinfo',
                         'profile_id', 'session_name',
@@ -290,14 +290,14 @@ class X2GoSession(object):
         self.ssh_rootdir = ssh_rootdir
         self.control_session = control_session
 
-        if params.has_key('published_applications'):
+        if 'published_applications' in params:
             self.published_applications = params['published_applications']
             if self.published_applications:
                 params['cmd'] = 'PUBLISHED'
         else:
             self.published_applications = params['published_applications'] = False
 
-        if params.has_key('cmd') and params['cmd'] != 'PUBLISHED':
+        if 'cmd' in params and params['cmd'] != 'PUBLISHED':
             self.published_applications = params['published_applications'] = False
         self.published_applications_menu = None
 
@@ -527,7 +527,7 @@ class X2GoSession(object):
         @type subsystem: C{str}
 
         """
-        if type(subsystem) in (types.StringType, types.UnicodeType):
+        if type(subsystem) in (bytes, str):
             _subsystem = '(%s) ' % subsystem
         else:
             _subsystem = ''
@@ -607,7 +607,7 @@ class X2GoSession(object):
         Initialize a new control session (C{X2GoControlSession*}).
 
         """
-        low_latency = self.terminal_params.has_key('link') and self.terminal_params['link'].lower() in ('modem', 'isdn')
+        low_latency = 'link' in self.terminal_params and self.terminal_params['link'].lower() in ('modem', 'isdn')
 
         if self.control_session is None:
             self.logger('initializing X2GoControlSession', loglevel=log.loglevel_DEBUG)
@@ -667,7 +667,7 @@ class X2GoSession(object):
         # retrieve an up-to-date list of sharable local folders from the client instance
         if self.client_instance:
             _exports = self.client_instance.get_profile_config(self.profile_name, 'export')
-            self.share_local_folders = [ sf for sf in _exports.keys() if _exports[sf] ]
+            self.share_local_folders = [ sf for sf in list(_exports.keys()) if _exports[sf] ]
 
         i = 0
         while i < max_wait:
@@ -811,17 +811,17 @@ class X2GoSession(object):
         except KeyError: pass
 
         if self.sshproxy_reuse_authinfo:
-            if params.has_key('key_filename'):
+            if 'key_filename' in params:
                 params['sshproxy_key_filename'] = params['key_filename']
-            if params.has_key('pkey'):
+            if 'pkey' in params:
                 params['sshproxy_pkey'] = params['pkey']
-            if params.has_key('password'):
+            if 'password' in params:
                 params['sshproxy_password'] = params['password']
 
         _terminal_params = copy.deepcopy(params)
         _control_params = copy.deepcopy(params)
         _sshproxy_params = copy.deepcopy(params)
-        for p in params.keys():
+        for p in list(params.keys()):
             if p in session._X2GO_TERMINAL_PARAMS:
                 del _control_params[p]
                 del _sshproxy_params[p]
@@ -996,7 +996,7 @@ class X2GoSession(object):
         """
         if self.has_terminal_session():
             return self.terminal_session.get_session_cmd()
-        if self.terminal_params.has_key('cmd'):
+        if 'cmd' in self.terminal_params:
             return self.terminal_params['cmd']
         return None
     __get_session_cmd = get_session_cmd
@@ -1135,17 +1135,17 @@ class X2GoSession(object):
 
         """
         if self.use_sshproxy:
-            if self.sshproxy_params.has_key('sshproxy_key_filename') and self.sshproxy_params['sshproxy_key_filename'] and os.path.exists(os.path.normpath(self.sshproxy_params['sshproxy_key_filename'])):
+            if 'sshproxy_key_filename' in self.sshproxy_params and self.sshproxy_params['sshproxy_key_filename'] and os.path.exists(os.path.normpath(self.sshproxy_params['sshproxy_key_filename'])):
                 return True
-            elif self.sshproxy_reuse_authinfo and self.control_params.has_key('key_filename') and self.control_params['key_filename'] and os.path.exists(os.path.normpath(self.control_params['key_filename'])):
+            elif self.sshproxy_reuse_authinfo and 'key_filename' in self.control_params and self.control_params['key_filename'] and os.path.exists(os.path.normpath(self.control_params['key_filename'])):
                 return True
-            elif self.sshproxy_params.has_key('sshproxy_pkey') and self.sshproxy_params['sshproxy_pkey']:
+            elif 'sshproxy_pkey' in self.sshproxy_params and self.sshproxy_params['sshproxy_pkey']:
                 return True
-            elif self.sshproxy_reuse_authinfo and self.control_params.has_key('pkey') and self.control_params['pkey']:
+            elif self.sshproxy_reuse_authinfo and 'pkey' in self.control_params and self.control_params['pkey']:
                 return True
-            elif self.sshproxy_params.has_key('sshproxy_look_for_keys') and self.sshproxy_params['sshproxy_look_for_keys'] and (os.path.exists(os.path.expanduser('~/.ssh/id_rsa')) or os.path.exists(os.path.expanduser('~/.ssh/id_dsa'))):
+            elif 'sshproxy_look_for_keys' in self.sshproxy_params and self.sshproxy_params['sshproxy_look_for_keys'] and (os.path.exists(os.path.expanduser('~/.ssh/id_rsa')) or os.path.exists(os.path.expanduser('~/.ssh/id_dsa'))):
                 return True
-            elif self.sshproxy_params.has_key('sshproxy_allow_agent') and self.sshproxy_params['sshproxy_allow_agent'] and paramiko.Agent().get_keys():
+            elif 'sshproxy_allow_agent' in self.sshproxy_params and self.sshproxy_params['sshproxy_allow_agent'] and paramiko.Agent().get_keys():
                 return True
             else:
                 return False
@@ -1169,19 +1169,19 @@ class X2GoSession(object):
         _can_sshproxy_auto_connect = self.can_sshproxy_auto_connect()
 
         # do we have a key file passed as control parameter?
-        if self.control_params.has_key('key_filename') and self.control_params['key_filename'] and os.path.exists(os.path.normpath(self.control_params['key_filename'])):
+        if 'key_filename' in self.control_params and self.control_params['key_filename'] and os.path.exists(os.path.normpath(self.control_params['key_filename'])):
             return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
 
         # or a private key?
-        elif self.control_params.has_key('pkey') and self.control_params['pkey']:
+        elif 'pkey' in self.control_params and self.control_params['pkey']:
             return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
 
         # or a key auto discovery?
-        elif self.control_params.has_key('look_for_keys') and self.control_params['look_for_keys'] and (os.path.exists(os.path.expanduser('~/.ssh/id_rsa')) or os.path.exists(os.path.expanduser('~/.ssh/id_dsa'))):
+        elif 'look_for_keys' in self.control_params and self.control_params['look_for_keys'] and (os.path.exists(os.path.expanduser('~/.ssh/id_rsa')) or os.path.exists(os.path.expanduser('~/.ssh/id_dsa'))):
             return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
 
         # or an SSH agent usage?
-        elif self.control_params.has_key('allow_agent') and self.control_params['allow_agent'] and paramiko.Agent().get_keys():
+        elif 'allow_agent' in self.control_params and self.control_params['allow_agent'] and paramiko.Agent().get_keys():
             return (_can_sshproxy_auto_connect is None) or _can_sshproxy_auto_connect
 
         else:
@@ -1296,13 +1296,13 @@ class X2GoSession(object):
                 self.control_params['passphrase'] = passphrase
 
             if self.sshproxy_reuse_authinfo:
-                if self.control_params.has_key('key_filename'):
+                if 'key_filename' in self.control_params:
                     self.sshproxy_params['sshproxy_key_filename'] = self.control_params['key_filename']
-                if self.control_params.has_key('pkey'):
+                if 'pkey' in self.control_params:
                     self.sshproxy_params['sshproxy_pkey'] = self.control_params['pkey']
-                if self.control_params.has_key('password'):
+                if 'password' in self.control_params:
                     self.sshproxy_params['sshproxy_password'] = self.control_params['password']
-                if self.control_params.has_key('passphrase'):
+                if 'passphrase' in self.control_params:
                     self.sshproxy_params['sshproxy_passphrase'] = self.control_params['passphrase']
 
             _params = {}
@@ -1318,29 +1318,29 @@ class X2GoSession(object):
                                                               session_instance=self,
                                                               forward_sshagent=self.forward_sshagent,
                                                               **_params)
-            except x2go_exceptions.X2GoControlSessionException, e:
+            except x2go_exceptions.X2GoControlSessionException as e:
                 raise x2go_exceptions.X2GoSessionException(str(e))
-            except x2go_exceptions.X2GoRemoteHomeException, e:
+            except x2go_exceptions.X2GoRemoteHomeException as e:
                 self.disconnect()
                 raise e
             except:
                 # remove credentials immediately
                 self.control_params['password'] = ''
-                if self.control_params and self.control_params.has_key('passphrase'):
+                if self.control_params and 'passphrase' in self.control_params:
                     del self.control_params['passphrase']
-                if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_password'):
+                if self.sshproxy_params and 'sshproxy_password' in self.sshproxy_params:
                     self.sshproxy_params['sshproxy_password'] = ''
-                if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_passphrase'):
+                if self.sshproxy_params and 'sshproxy_passphrase' in self.sshproxy_params:
                     del self.sshproxy_params['sshproxy_passphrase']
                 raise
             finally:
                 # remove credentials immediately
                 self.control_params['password'] = ''
-                if self.control_params and self.control_params.has_key('passphrase'):
+                if self.control_params and 'passphrase' in self.control_params:
                     del self.control_params['passphrase']
-                if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_password'):
+                if self.sshproxy_params and 'sshproxy_password' in self.sshproxy_params:
                     self.sshproxy_params['sshproxy_password'] = ''
-                if self.sshproxy_params and self.sshproxy_params.has_key('sshproxy_passphrase'):
+                if self.sshproxy_params and 'sshproxy_passphrase' in self.sshproxy_params:
                     del self.sshproxy_params['sshproxy_passphrase']
 
             if not self.connected:
@@ -1457,7 +1457,7 @@ class X2GoSession(object):
         @type kwargs: C{dict}
 
         """
-        if type(print_action) is not types.StringType:
+        if type(print_action) is not bytes:
             return False
         self.terminal_session.set_print_action(print_action, **kwargs)
     __set_print_action = set_print_action
@@ -1601,7 +1601,7 @@ class X2GoSession(object):
             try:
                 session_list = self.control_session.list_sessions()
                 self.connected = True
-            except x2go_exceptions.X2GoControlSessionException, e:
+            except x2go_exceptions.X2GoControlSessionException as e:
                 self.connected = False
                 self.running = None
                 self.suspended = None
@@ -1618,7 +1618,7 @@ class X2GoSession(object):
                     self.terminated = not (self.running or self.suspended)
                 else:
                     self.terminated = None
-            except KeyError, e:
+            except KeyError as e:
                 self.running = False
                 self.suspended = False
                 if not self.virgin:
@@ -1725,7 +1725,7 @@ class X2GoSession(object):
                 session_infos = self.list_sessions()
 
                 # only auto start/resume non-pubapp sessions
-                for session_name in session_infos.keys():
+                for session_name in list(session_infos.keys()):
                     if session_infos[session_name].is_published_applications_provider():
                         del session_infos[session_name]
 
@@ -1738,7 +1738,7 @@ class X2GoSession(object):
                         if sorted_session_names[-1].find('RDP') == -1:
                             return self.resume(session_name=sorted_session_names[0])
                     elif all_suspended:
-                        for session_name in [ _sn for _sn in session_infos.keys() if session_infos[_sn].is_suspended() ]:
+                        for session_name in [ _sn for _sn in list(session_infos.keys()) if session_infos[_sn].is_suspended() ]:
                             return self.resume(session_name=session_name)
                 else:
                     if not self.published_applications:
@@ -1902,7 +1902,7 @@ class X2GoSession(object):
                                                         session_instance=self,
                                                         session_list=session_list,
                                                         logger=self.logger, **self.terminal_params)
-            except x2go_exceptions.X2GoControlSessionException, e:
+            except x2go_exceptions.X2GoControlSessionException as e:
                 self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
                 self.HOOK_on_control_session_death()
                 self._X2GoSession__disconnect()
@@ -1956,7 +1956,7 @@ class X2GoSession(object):
                        (self._SUPPORTED_MIMEBOX and self.allow_mimebox) or \
                        (self._SUPPORTED_FOLDERSHARING and self.allow_share_local_folders):
                         self.has_terminal_session() and not self.faulty and self.terminal_session.start_sshfs()
-                except x2go_exceptions.X2GoUserException, e:
+                except x2go_exceptions.X2GoUserException as e:
                     self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
                     self.HOOK_sshfs_not_available()
                     self._SUPPORTED_PRINTING = False
@@ -1970,11 +1970,11 @@ class X2GoSession(object):
                     try:
                         self.has_terminal_session() and not self.faulty and self.terminal_session.start_printing()
                         self.has_terminal_session() and not self.faulty and self.session_environment.update({'X2GO_SPOOLDIR': self.terminal_session.get_printing_spooldir(), })
-                    except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException), e:
+                    except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException) as e:
                         self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
                         self.HOOK_printing_not_available()
                         self._SUPPORTED_PRINTING = False
-                    except x2go_exceptions.X2GoControlSessionException, e:
+                    except x2go_exceptions.X2GoControlSessionException as e:
                         self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
                         self.HOOK_on_control_session_death()
                         self._X2GoSession__disconnect()
@@ -1987,11 +1987,11 @@ class X2GoSession(object):
                     try:
                         self.has_terminal_session() and not self.faulty and self.terminal_session.start_mimebox(mimebox_extensions=self.mimebox_extensions, mimebox_action=self.mimebox_action)
                         self.has_terminal_session() and self.session_environment.update({'X2GO_MIMEBOX': self.terminal_session.get_mimebox_spooldir(), })
-                    except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException), e:
+                    except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException) as e:
                         self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
                         self.HOOK_mimebox_not_available()
                         self._SUPPORTED_MIMEBOX = False
-                    except x2go_exceptions.X2GoControlSessionException, e:
+                    except x2go_exceptions.X2GoControlSessionException as e:
                         self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
                         self.HOOK_on_control_session_death()
                         self._X2GoSession__disconnect()
@@ -2004,7 +2004,7 @@ class X2GoSession(object):
                 if _new_session:
                     try:
                         self.has_terminal_session() and self.terminal_session.run_command(env=self.session_environment)
-                    except x2go_exceptions.X2GoControlSessionException, e:
+                    except x2go_exceptions.X2GoControlSessionException as e:
                         self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
                         self.HOOK_on_control_session_death()
                         self._X2GoSession__disconnect()
@@ -2207,7 +2207,7 @@ class X2GoSession(object):
                 # session, run this pre-set command now...
                 try:
                     self.terminal_session.run_command(env=self.session_environment)
-                except x2go_exceptions.X2GoControlSessionException, e:
+                except x2go_exceptions.X2GoControlSessionException as e:
                     self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
                     self.HOOK_on_control_session_death()
                     self._X2GoSession__disconnect()
@@ -2497,7 +2497,7 @@ class X2GoSession(object):
         """
         _depth_local = utils.local_color_depth()
         _depth_session = self.color_depth_from_session_name()
-        if type(_depth_session) == types.IntType:
+        if type(_depth_session) == int:
             return utils.is_color_depth_ok(depth_session=_depth_session, depth_local=_depth_local)
 
         # we assume the color depth is ok, if _depth_session could not be obtained from the session name
@@ -2612,11 +2612,11 @@ class X2GoSession(object):
         # remember exported folders for restoring them on session suspension/termination
         if self.client_instance and self.restore_shared_local_folders:
             _exported_folders = copy.deepcopy(self._restore_exported_folders)
-            for folder in [ sf for sf in self.shared_folders.keys() if self.shared_folders[sf]['status'] in ('new', 'mounted') ]:
-                _exported_folders.update({ unicode(folder): True })
-            for folder in _exported_folders.keys():
-                if folder in [ sf for sf in self.shared_folders.keys() if self.shared_folders[sf]['status'] == 'unmounted' ]:
-                    _exported_folders.update({ unicode(folder): False })
+            for folder in [ sf for sf in list(self.shared_folders.keys()) if self.shared_folders[sf]['status'] in ('new', 'mounted') ]:
+                _exported_folders.update({ str(folder): True })
+            for folder in list(_exported_folders.keys()):
+                if folder in [ sf for sf in list(self.shared_folders.keys()) if self.shared_folders[sf]['status'] == 'unmounted' ]:
+                    _exported_folders.update({ str(folder): False })
             self._restore_exported_folders = _exported_folders
 
     def share_local_folder(self, local_path=None, folder_name=None, update_exported_folders=True):
@@ -2641,14 +2641,14 @@ class X2GoSession(object):
         # compat for Python-X2Go (<=0.1.1.6)
         if folder_name: local_path=folder_name
 
-        local_path = unicode(local_path)
+        local_path = str(local_path)
 
         retval = False
         if self.has_terminal_session():
             if self.is_folder_sharing_available() and self.is_master_session():
 
                 # for the sake of non-blocking I/O: let's pretend the action has already been successful
-                if self.shared_folders.has_key(local_path):
+                if local_path in self.shared_folders:
                     self.shared_folders[local_path]['status'] = 'mounted'
                 else:
                     self.shared_folders.update({ local_path: { 'status': 'new', 'mountpoint': '', }, })
@@ -2666,7 +2666,7 @@ class X2GoSession(object):
 
                         # disable this local folder in session profile if restoring shared folders for following sessions is activated
                         if self.client_instance and self.restore_shared_local_folders:
-                            if local_path in self._restore_exported_folders.keys():
+                            if local_path in list(self._restore_exported_folders.keys()):
                                 self._restore_exported_folders[local_path] = False
 
                 except x2go_exceptions.X2GoControlSessionException:
@@ -2705,10 +2705,10 @@ class X2GoSession(object):
                     for _folder in self.share_local_folders:
                         try:
                             retval = self.share_local_folder(_folder, update_exported_folders=False) and retval
-                        except x2go_exceptions.X2GoUserException, e:
+                        except x2go_exceptions.X2GoUserException as e:
                             retval = False
                             self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
-                        except x2go_exceptions.X2GoControlSessionException, e:
+                        except x2go_exceptions.X2GoControlSessionException as e:
                             retval = False
                             self.logger('%s' % str(e), loglevel=log.loglevel_ERROR)
                             self.HOOK_on_control_session_death()
@@ -2743,10 +2743,10 @@ class X2GoSession(object):
         """
         retval = False
 
-        local_path = unicode(local_path)
+        local_path = str(local_path)
 
         if self.has_terminal_session():
-            if self.is_folder_sharing_available() and self.is_master_session() and local_path in self.shared_folders.keys():
+            if self.is_folder_sharing_available() and self.is_master_session() and local_path in list(self.shared_folders.keys()):
 
                 # for the sake of non-blocking I/O: let's pretend the action has already been successful
                 self.shared_folders[local_path]['status'] = 'unmounted'
@@ -2795,7 +2795,7 @@ class X2GoSession(object):
                 else:
                     retval = True
                     _shared_folders = copy.deepcopy(self.shared_folders)
-                    for _folder in _shared_folders.keys():
+                    for _folder in list(_shared_folders.keys()):
                         retval = self.unshare_local_folder(_folder, update_exported_folders=False) and retval
                     if update_exported_folders:
                         self._update_restore_exported_folders()
@@ -2825,9 +2825,9 @@ class X2GoSession(object):
             unshared_folders = []
             if mounts is None:
                 mounts = self.list_mounts()
-            _defacto_mounts = [ unicode(m.split('|')[1].split('/')[-1]) for m in mounts ]
+            _defacto_mounts = [ str(m.split('|')[1].split('/')[-1]) for m in mounts ]
 
-            for shared_folder in self.shared_folders.keys():
+            for shared_folder in list(self.shared_folders.keys()):
 
                 if _X2GOCLIENT_OS == 'Windows':
                     _driveletter, _path = os.path.splitdrive(shared_folder)
@@ -2839,17 +2839,17 @@ class X2GoSession(object):
                     _mount_point = _mount_point.replace(' ', '_')
 
                 self.shared_folders[shared_folder]['status'] = 'mounted'
-                self.shared_folders[shared_folder]['mountpoint'] = unicode(_mount_point)
+                self.shared_folders[shared_folder]['mountpoint'] = str(_mount_point)
 
             for m in _defacto_mounts:
-                for sf in self.shared_folders.keys():
+                for sf in list(self.shared_folders.keys()):
                     if self.shared_folders[sf]['mountpoint'] == m:
                         self.shared_folders[sf]['status'] = 'mounted'
                         break
 
             unshared_folders = False
 
-            for sf in self.shared_folders.keys():
+            for sf in list(self.shared_folders.keys()):
                 m = self.shared_folders[sf]['mountpoint']
                 if m and m not in _defacto_mounts:
                     try:
@@ -2863,7 +2863,7 @@ class X2GoSession(object):
             if unshared_folders:
                 self._update_restore_exported_folders()
 
-        return [ unicode(sf) for sf in self.shared_folders if self.shared_folders[sf]['status'] in ('new', 'mounted') ]
+        return [ str(sf) for sf in self.shared_folders if self.shared_folders[sf]['status'] in ('new', 'mounted') ]
     __get_shared_folders = get_shared_folders
 
     def session_cleanup(self):
diff --git a/x2go/sftpserver.py b/x2go/sftpserver.py
index fd4ed31..3e66b9a 100644
--- a/x2go/sftpserver.py
+++ b/x2go/sftpserver.py
@@ -39,9 +39,9 @@ import paramiko
 import gevent
 
 # Python X2Go modules
-import rforward
-import defaults
-import log
+from . import rforward
+from . import defaults
+from . import log
 
 class _SSHServer(paramiko.ServerInterface):
     """\
@@ -145,7 +145,7 @@ class _SFTPHandle(paramiko.SFTPHandle):
         """
         try:
             return paramiko.SFTPAttributes.from_stat(os.fstat(self.readfile.fileno()))
-        except OSError, e:
+        except OSError as e:
             return paramiko.SFTPServer.convert_errno(e.errno)
 
 
@@ -228,12 +228,12 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
                     attr.filename = fname
                     self.logger('sFTP server %s: file attributes ok: %s' % (self, fname), loglevel=log.loglevel_DEBUG_SFTPXFER)
                     out.append(attr)
-                except OSError, e:
+                except OSError as e:
                     self.logger('sFTP server %s: encountered error processing attributes of file %s: %s' % (self, fname, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
 
             self.logger('sFTP server: folder list is : %s' % str([ a.filename for a in out ]), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return out
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
 
@@ -252,7 +252,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
         self.logger('sFTP server %s: calling stat on path: %s' % (self, path), loglevel=log.loglevel_DEBUG_SFTPXFER)
         try:
             return paramiko.SFTPAttributes.from_stat(os.stat(path))
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
 
@@ -271,7 +271,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
         self.logger('sFTP server: calling lstat on path: %s' % path, loglevel=log.loglevel_DEBUG_SFTPXFER)
         try:
             return paramiko.SFTPAttributes.from_stat(os.lstat(path))
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
 
@@ -301,8 +301,8 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
             else:
                 # os.open() defaults to 0777 which is
                 # an odd default mode for files
-                fd = os.open(path, flags, 0666)
-        except OSError, e:
+                fd = os.open(path, flags, 0o666)
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
         if (flags & os.O_CREAT) and (attr is not None):
@@ -323,7 +323,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
             fstr = 'rb'
         try:
             f = os.fdopen(fd, fstr)
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
         fobj = _SFTPHandle(flags)
@@ -366,7 +366,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
         newpath = self._realpath(newpath)
         try:
             shutil.move(oldpath, newpath)
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
         return paramiko.SFTP_OK
@@ -388,7 +388,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
         path = self._realpath(path)
         try:
             os.mkdir(path, attr.st_mode)
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
         return paramiko.SFTP_OK
@@ -408,7 +408,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
         path = self._realpath(path)
         try:
             shutil.rmtree(path)
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
         return paramiko.SFTP_OK
@@ -433,7 +433,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
                 os.chmod(path, attr.st_mode)
             if attr.st_uid is not None:
                 os.chown(path, attr.st_uid, attr.st_gid)
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
         return paramiko.SFTP_OK
@@ -457,7 +457,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
             target_path = self._realpath(target_path)
         try:
             os.symlink(target_path, path)
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
         return paramiko.SFTP_OK
@@ -476,7 +476,7 @@ class _SFTPServerInterface(paramiko.SFTPServerInterface):
         path = self._realpath(path)
         try:
             return os.readlink(path)
-        except OSError, e:
+        except OSError as e:
             self.logger('sFTP server %s: encountered error: %s' % (self, str(e)), loglevel=log.loglevel_DEBUG_SFTPXFER)
             return paramiko.SFTPServer.convert_errno(e.errno)
 
diff --git a/x2go/sshproxy.py b/x2go/sshproxy.py
index 3036bb0..690c225 100644
--- a/x2go/sshproxy.py
+++ b/x2go/sshproxy.py
@@ -35,11 +35,11 @@ import string
 import random
 
 # Python X2Go modules
-import forward
-import checkhosts
-import log
-import utils
-import x2go_exceptions
+from . import forward
+from . import checkhosts
+from . import log
+from . import utils
+from . import x2go_exceptions
 
 from x2go.defaults import CURRENT_LOCAL_USER as _CURRENT_LOCAL_USER
 from x2go.defaults import LOCAL_HOME as _LOCAL_HOME
@@ -150,9 +150,9 @@ class X2GoSSHProxy(paramiko.SSHClient, threading.Thread):
             self.logger = copy.deepcopy(logger)
         self.logger.tag = __NAME__
 
-        if hostname and hostname in (types.UnicodeType, types.StringType):
+        if hostname and hostname in (str, bytes):
             hostname = [hostname]
-        if hostname and hostname in (types.ListType, types.TupleType):
+        if hostname and hostname in (list, tuple):
             hostname = random.choice(list(hostname))
         self.hostname, self.port, self.username = hostname, port, username
 
@@ -161,9 +161,9 @@ class X2GoSSHProxy(paramiko.SSHClient, threading.Thread):
         # translate between X2GoSession options and paramiko.SSHCLient.connect() options
         # if <hostname>:<port> is used for sshproxy_host, then this <port> is used
         if sshproxy_host:
-            if sshproxy_host and type(sshproxy_host) in (types.UnicodeType, types.StringType):
+            if sshproxy_host and type(sshproxy_host) in (str, bytes):
                 sshproxy_host = [sshproxy_host]
-            if type(sshproxy_host) in (types.ListType, types.TupleType):
+            if type(sshproxy_host) in (list, tuple):
                 sshproxy_host = random.choice(list(sshproxy_host))
             if sshproxy_host.find(':'):
                 self.hostname = sshproxy_host.split(':')[0]
@@ -185,15 +185,15 @@ class X2GoSSHProxy(paramiko.SSHClient, threading.Thread):
             self.local_port = int(self.local_port)
             self.remote_port = int(self.remote_port)
         else:
-            if local_host and type(local_host) in (types.UnicodeType, types.StringType):
+            if local_host and type(local_host) in (str, bytes):
                 local_host = [local_host]
-            if local_host and type(local_host) in (types.ListType, types.TupleType):
+            if local_host and type(local_host) in (list, tuple):
                 local_host = random.choice(list(local_host))
-            if remote_host and type(remote_host) in (types.UnicodeType, types.StringType):
+            if remote_host and type(remote_host) in (str, bytes):
                 remote_host = [remote_host]
-            if remote_host and type(remote_host) in (types.ListType, types.TupleType):
+            if remote_host and type(remote_host) in (list, tuple):
                 remote_host = random.choice(remote_host)
-            print "LOCAL_HOST: ", local_host
+            print("LOCAL_HOST: ", local_host)
             self.local_host = local_host
             self.local_port = int(local_port)
             self.remote_host =  remote_host
@@ -226,7 +226,7 @@ class X2GoSSHProxy(paramiko.SSHClient, threading.Thread):
         if username is None:
             username = _CURRENT_LOCAL_USER
 
-        if type(password) not in (types.StringType, types.UnicodeType):
+        if type(password) not in (bytes, str):
             password = ''
 
         self._keepalive = True
@@ -279,7 +279,7 @@ class X2GoSSHProxy(paramiko.SSHClient, threading.Thread):
                                      allow_agent=allow_agent,
                                     )
 
-                except (paramiko.PasswordRequiredException, paramiko.SSHException), e:
+                except (paramiko.PasswordRequiredException, paramiko.SSHException) as e:
                     self.close()
                     if type(e) == paramiko.SSHException and str(e).startswith('Two-factor authentication requires a password'):
                         self.logger('SSH proxy host requests two-factor authentication', loglevel=log.loglevel_NOTICE)
@@ -328,7 +328,7 @@ class X2GoSSHProxy(paramiko.SSHClient, threading.Thread):
                                                  look_for_keys=look_for_keys,
                                                  allow_agent=allow_agent,
                                                 )
-                        except x2go_exceptions.AuthenticationException, auth_e:
+                        except x2go_exceptions.AuthenticationException as auth_e:
                             raise x2go_exceptions.X2GoSSHProxyAuthenticationException(str(auth_e))
 
                     else:
@@ -370,7 +370,7 @@ class X2GoSSHProxy(paramiko.SSHClient, threading.Thread):
                     self.close()
                     raise
 
-        except (x2go_exceptions.SSHException, IOError), e:
+        except (x2go_exceptions.SSHException, IOError) as e:
             self.close()
             raise x2go_exceptions.X2GoSSHProxyException(str(e))
         except:
diff --git a/x2go/telekinesis.py b/x2go/telekinesis.py
index 21a63a2..babb747 100644
--- a/x2go/telekinesis.py
+++ b/x2go/telekinesis.py
@@ -159,7 +159,7 @@ class X2GoTelekinesisClient(threading.Thread):
             self.logger('Shutting down Telekinesis client subprocess', loglevel=log.loglevel_DEBUG)
             try:
                 self.tekiclient.kill()
-            except OSError, e:
+            except OSError as e:
                 self.logger('Telekinesis client shutdown gave a message that we may ignore: %s' % str(e), loglevel=log.loglevel_WARN)
             self.tekiclient = None
 
@@ -218,7 +218,7 @@ class X2GoTelekinesisClient(threading.Thread):
 
         try:
             os.makedirs(self.session_info.local_container)
-        except OSError, e:
+        except OSError as e:
             if e.errno == 17:
                 # file exists
                 pass
@@ -262,7 +262,7 @@ class X2GoTelekinesisClient(threading.Thread):
         try:
             p.terminate()
             self.logger('terminating Telekinesis client: %s' % p, loglevel=log.loglevel_DEBUG)
-        except OSError, e:
+        except OSError as e:
             if e.errno == 3:
                 # No such process
                 pass
@@ -320,7 +320,7 @@ class X2GoTelekinesisClient(threading.Thread):
         self.tekiclient_datalog_stderr = open('%s/%s' % (self.session_info.local_container, self.tekiclient_datalog, ), 'a')
         try:
             os.makedirs(os.path.normpath('/tmp/.x2go-{local_user}/telekinesis/S-{sid}/'.format(local_user=_CURRENT_LOCAL_USER, sid=self.session_name)))
-        except OSError, e:
+        except OSError as e:
             if e.errno == 17:
                 # file exists
                 pass
@@ -352,7 +352,7 @@ class X2GoTelekinesisClient(threading.Thread):
                                                       stdout=self.tekiclient_datalog_stdout,
                                                       stderr=self.tekiclient_datalog_stderr,
                                                       shell=False)
-        except OSError, e:
+        except OSError as e:
             if e.errno == 2:
                 self.logger("The 'sshfs' command is not available on your client machine, please install it to get Telekinesis up and running!!!", loglevel=log.loglevel_WARN)
             else:
diff --git a/x2go/tests/__init__.py b/x2go/tests/__init__.py
index 9053e98..a14dc13 100644
--- a/x2go/tests/__init__.py
+++ b/x2go/tests/__init__.py
@@ -24,5 +24,5 @@ base = os.path.join(os.path.split(os.path.split(os.getcwd())[0])[0])
 # prepend the X2Go path (useful for building new packages)
 sys.path = [ os.path.normpath(base), ] + sys.path
 
-import runalltests
-import test_printing
+from . import runalltests
+from . import test_printing
diff --git a/x2go/tests/test_printing.py b/x2go/tests/test_printing.py
index 2457d89..6d04dfe 100644
--- a/x2go/tests/test_printing.py
+++ b/x2go/tests/test_printing.py
@@ -40,7 +40,7 @@ command=xpdf
 defaultprinter=PDF
 """
         tf = tempfile.NamedTemporaryFile()
-        print >> tf, _printing
+        print(_printing, file=tf)
         tf.seek(0)
         p_action = x2go.backends.printing.X2GoClientPrinting(config_files=tf.name, client_instance='DUMMY')
         self.assertEqual(type(p_action.print_action), x2go.printactions.X2GoPrintActionDIALOG)
@@ -60,7 +60,7 @@ command=xpdf
 defaultprinter=PDF
 """
         tf = tempfile.NamedTemporaryFile()
-        print >> tf, _printing
+        print(_printing, file=tf)
         tf.seek(0)
         p_action = x2go.backends.printing.X2GoClientPrinting(config_files=tf.name)
         self.assertEqual(type(p_action.print_action), x2go.printactions.X2GoPrintActionPDFVIEW)
@@ -80,7 +80,7 @@ command=xpdf
 defaultprinter=PDF
 """
         tf = tempfile.NamedTemporaryFile()
-        print >> tf, _printing
+        print(_printing, file=tf)
         tf.seek(0)
         p_action = x2go.backends.printing.X2GoClientPrinting(config_files=tf.name)
         self.assertEqual(type(p_action.print_action), x2go.printactions.X2GoPrintActionPDFSAVE)
@@ -100,7 +100,7 @@ command=xpdf
 defaultprinter=PDF
 """
         tf = tempfile.NamedTemporaryFile()
-        print >> tf, _printing
+        print(_printing, file=tf)
         tf.seek(0)
         p_action = x2go.backends.printing.X2GoClientPrinting(config_files=tf.name)
         self.assertEqual(type(p_action.print_action), x2go.printactions.X2GoPrintActionPRINT)
@@ -120,7 +120,7 @@ command=xpdf
 defaultprinter=PDF
 """
         tf = tempfile.NamedTemporaryFile()
-        print >> tf, _printing
+        print(_printing, file=tf)
         tf.seek(0)
         p_action = x2go.backends.printing.X2GoClientPrinting(config_files=tf.name)
         self.assertEqual(type(p_action.print_action), x2go.printactions.X2GoPrintActionPRINTCMD)
diff --git a/x2go/utils.py b/x2go/utils.py
index 2cd9725..5b89cd5 100644
--- a/x2go/utils.py
+++ b/x2go/utils.py
@@ -37,18 +37,18 @@ import distutils.version
 import paramiko
 
 # Python X2Go modules
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
-from defaults import X2GO_SESSIONPROFILE_DEFAULTS as _X2GO_SESSIONPROFILE_DEFAULTS
-from defaults import X2GO_MIMEBOX_ACTIONS as _X2GO_MIMEBOX_ACTIONS
-from defaults import pack_methods_nx3
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import X2GO_SESSIONPROFILE_DEFAULTS as _X2GO_SESSIONPROFILE_DEFAULTS
+from .defaults import X2GO_MIMEBOX_ACTIONS as _X2GO_MIMEBOX_ACTIONS
+from .defaults import pack_methods_nx3
 
-from defaults import BACKENDS as _BACKENDS
+from .defaults import BACKENDS as _BACKENDS
 
-import x2go_exceptions
+from . import x2go_exceptions
 
 if _X2GOCLIENT_OS != 'Windows':
     import Xlib
-    from defaults import X_DISPLAY as _X_DISPLAY
+    from .defaults import X_DISPLAY as _X_DISPLAY
 
 if _X2GOCLIENT_OS == 'Windows':
     import win32gui
@@ -104,7 +104,7 @@ def slugify(value):
 
     """
     import unicodedata
-    value = unicodedata.normalize('NFKD', unicode(value)).encode('ascii', 'ignore')
+    value = unicodedata.normalize('NFKD', str(value)).encode('ascii', 'ignore')
     value = re.sub('[^\w\s-]', '', value).strip().lower()
     value = re.sub('[(]', '<', value).strip().lower()
     value = re.sub('[)]', '>', value).strip().lower()
@@ -135,10 +135,10 @@ def _checkIniFileDefaults(data_structure):
     """
     if data_structure is None:
         return False
-    if type(data_structure) is not types.DictType:
+    if type(data_structure) is not dict:
         return False
-    for sub_dict in data_structure.values():
-        if type(sub_dict) is not types.DictType:
+    for sub_dict in list(data_structure.values()):
+        if type(sub_dict) is not dict:
             return False
     return True
 
@@ -156,7 +156,7 @@ def _checkSessionProfileDefaults(data_structure):
     """
     if data_structure is None:
         return False
-    if type(data_structure) is not types.DictType:
+    if type(data_structure) is not dict:
         return False
     return True
 
@@ -176,8 +176,8 @@ def _convert_SessionProfileOptions_2_SessionParams(options):
     _params = copy.deepcopy(options)
 
     # get rid of unknown session profile options
-    _known_options = _X2GO_SESSIONPROFILE_DEFAULTS.keys()
-    for p in _params.keys():
+    _known_options = list(_X2GO_SESSIONPROFILE_DEFAULTS.keys())
+    for p in list(_params.keys()):
         if p not in _known_options:
             del _params[p]
 
@@ -229,10 +229,10 @@ def _convert_SessionProfileOptions_2_SessionParams(options):
             '4': 'lan',
     }
 
-    for opt, val in options.iteritems():
+    for opt, val in options.items():
 
         # rename options if necessary
-        if opt in _rename_dict.keys():
+        if opt in list(_rename_dict.keys()):
             del _params[opt]
             opt = _rename_dict[opt]
             if opt in _known_options:
@@ -244,14 +244,14 @@ def _convert_SessionProfileOptions_2_SessionParams(options):
         # translate integer values for connection speed to readable strings
         if opt == 'link':
             val = str(val).lower()
-            if val in _speed_dict.keys():
+            if val in list(_speed_dict.keys()):
                 val = _speed_dict[val]
             val = val.lower()
             _params['link'] = val
 
         # share_local_folders is a list
         if opt in ('share_local_folders', 'mimebox_extensions'):
-            if type(val) is types.StringType:
+            if type(val) is bytes:
                 if val:
                     _params[opt] = val.split(',')
                 else:
@@ -271,14 +271,14 @@ def _convert_SessionProfileOptions_2_SessionParams(options):
 
     del _params['fstunnel']
 
-    if _params.has_key('export'):
+    if 'export' in _params:
 
         _export = _params['export']
         del _params['export']
-        if type(_export) is types.DictType:
+        if type(_export) is dict:
 
             # since Python X2Go 0.5.0.0
-            _params['share_local_folders'] = _export.keys()
+            _params['share_local_folders'] = list(_export.keys())
 
         else:
 
@@ -318,7 +318,7 @@ def _convert_SessionProfileOptions_2_SessionParams(options):
         _params['session_type'] = 'application'
     del _params['rootless']
 
-    if _params['mimebox_action'] not in _X2GO_MIMEBOX_ACTIONS.keys():
+    if _params['mimebox_action'] not in list(_X2GO_MIMEBOX_ACTIONS.keys()):
         _params['mimebox_action'] = 'OPEN'
 
     if not options['usekbd']:
@@ -346,7 +346,7 @@ def _convert_SessionProfileOptions_2_SessionParams(options):
     if _params['use_sshproxy']:
 
         # compat code for Python X2Go 0.2.1.0 -> 0.2.2.0
-        if options.has_key('sshproxytunnel'):
+        if 'sshproxytunnel' in options:
             if not options['sshproxytunnel'].startswith('DEPRECATED'):
                 _params['server'] = options['sshproxytunnel'].split(":")[-2]
                 _params['port'] = options['sshproxytunnel'].split(":")[-1]
@@ -387,7 +387,7 @@ def session_names_by_timestamp(session_infos):
     @rtype: C{list}
 
     """
-    session_names = session_infos.keys()
+    session_names = list(session_infos.keys())
     sortable_session_names = [ '%s|%s' % (session_name.split('-')[-1].split('_')[0], session_name) for session_name in session_names ]
     sortable_session_names.sort()
     return [ session_name.split('|')[1] for session_name in sortable_session_names ]
@@ -404,7 +404,7 @@ def touch_file(filename, mode='a'):
 
     """
     if not os.path.isdir(os.path.dirname(filename)):
-        os.makedirs(os.path.dirname(filename), mode=00700)
+        os.makedirs(os.path.dirname(filename), mode=0o0700)
     f = open(filename, mode=mode)
     f.close()
 
@@ -434,8 +434,8 @@ def known_encodings():
     """
     from encodings.aliases import aliases
     _raw_encname_list = []
-    _raw_encname_list.extend(aliases.keys())
-    _raw_encname_list.extend(aliases.values())
+    _raw_encname_list.extend(list(aliases.keys()))
+    _raw_encname_list.extend(list(aliases.values()))
     _raw_encname_list.sort()
     _encname_list = []
     for _raw_encname in _raw_encname_list:
@@ -557,7 +557,7 @@ def local_color_depth():
     if _X2GOCLIENT_OS != 'Windows':
         try:
             p = subprocess.Popen(['xwininfo', '-root',], stdout=subprocess.PIPE, )
-            _depth_line = [ _info.strip() for _info in p.stdout.read().split('\n') if 'Depth:' in _info ][0]
+            _depth_line = [ _info.strip() for _info in p.stdout.read().decode().split('\n') if 'Depth:' in _info ][0]
             _depth = _depth_line.split(' ')[1]
             return int(_depth)
         except IndexError:
@@ -793,7 +793,7 @@ class ProgressStatus(object):
     A simple progress status iterator class.
 
     """
-    def __init__(self, progress_event, progress_func=range(0, 100, 10)):
+    def __init__(self, progress_event, progress_func=list(range(0, 100, 10))):
         """\
         @param progress_event: a threading.Event() object that gets notified on progress
         @type progress_event: C{obj}
@@ -812,7 +812,7 @@ class ProgressStatus(object):
         self.status = self.progress_func()
         return self
 
-    def next(self):
+    def __next__(self):
         """\
         On each iteration wait for the progress event to get triggered from an outside
         part of the application.
@@ -832,13 +832,15 @@ class ProgressStatus(object):
 def _get_backend_class(backend, class_name):
     # silence pyflakes, the _this_class var will be assigned in an exec() statement below...
     _this_class = None
-    if type(backend) not in (types.StringType, types.UnicodeType): return backend
+    if type(backend) not in (bytes, str): return backend
     backend = backend.upper()
-    available_backends = [ k for k in _BACKENDS[class_name].keys() if k != 'default' ]
+    available_backends = [ k for k in list(_BACKENDS[class_name].keys()) if k != 'default' ]
     # if for backend is given 'default' use the default backend module
     if backend == 'default': backend = _BACKENDS[class_name]['default']
     if backend in available_backends:
-        exec("from {backend} import {class_name} as _this_class".format(backend=_BACKENDS[class_name][backend], class_name=class_name))
+        namespace = {}
+        exec("from {backend} import {class_name} as _this_class".format(backend=_BACKENDS[class_name][backend], class_name=class_name), namespace)
+        _this_class = namespace['_this_class']
     else:
         raise x2go_exceptions.X2GoBackendException('unknown backend name %s for class %s' % (backend, class_name))
     return _this_class
@@ -859,9 +861,9 @@ def genkeypair(local_username, client_address, key_type='RSA'):
     pubkey = None
 
     # generate key pair
-    if unicode(key_type) == u'RSA':
+    if str(key_type) == 'RSA':
         key = paramiko.RSAKey.generate(2048)
-    elif unicode(key_type) == u'DSA':
+    elif str(key_type) == 'DSA':
         key = paramiko.DSSKey.generate(1024)
 
     if key:
diff --git a/x2go/x2go_exceptions.py b/x2go/x2go_exceptions.py
index 7f24d14..ee9067c 100644
--- a/x2go/x2go_exceptions.py
+++ b/x2go/x2go_exceptions.py
@@ -25,9 +25,8 @@ __NAME__ = 'x2goexceptions-pylib'
 
 # modules
 import paramiko
-import exceptions
 
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 
 # Python X2Go Exceptions
 AuthenticationException = paramiko.AuthenticationException
@@ -39,7 +38,7 @@ BadHostKeyException = paramiko.BadHostKeyException
 SSHException = paramiko.SSHException
 """inherited from Python Paramiko library"""
 
-class _X2GoException(exceptions.BaseException): pass
+class _X2GoException(BaseException): pass
 class X2GoClientException(_X2GoException): pass
 class X2GoClientPrintingException(_X2GoException): pass
 class X2GoClientSettingsException(_X2GoException): pass
diff --git a/x2go/xserver.py b/x2go/xserver.py
index 120d978..f91c93f 100644
--- a/x2go/xserver.py
+++ b/x2go/xserver.py
@@ -25,7 +25,7 @@
 
 __NAME__ = 'x2goxserver-pylib'
 
-from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
+from .defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 if _X2GOCLIENT_OS == 'Windows':
     import wmi
     import win32process
@@ -37,11 +37,11 @@ import gevent
 import copy
 
 # Python X2Go modules
-import log
-from defaults import X2GO_XCONFIG_CONFIGFILES as _X2GO_XCONFIG_CONFIGFILES
-from defaults import X2GO_CLIENTXCONFIG_DEFAULTS as _X2GO_CLIENTXCONFIG_DEFAULTS
-import inifiles
-import utils
+from . import log
+from .defaults import X2GO_XCONFIG_CONFIGFILES as _X2GO_XCONFIG_CONFIGFILES
+from .defaults import X2GO_CLIENTXCONFIG_DEFAULTS as _X2GO_CLIENTXCONFIG_DEFAULTS
+from . import inifiles
+from . import utils
 
 class X2GoClientXConfig(inifiles.X2GoIniFile):
     """\
@@ -79,7 +79,7 @@ class X2GoClientXConfig(inifiles.X2GoIniFile):
         """
         if _X2GOCLIENT_OS not in ("Windows"):
             import exceptions
-            class OSNotSupportedException(exceptions.StandardError): pass
+            class OSNotSupportedException(exceptions.Exception): pass
             raise OSNotSupportedException('classes of x2go.xserver module are for Windows only')
 
         inifiles.X2GoIniFile.__init__(self, config_files, defaults=defaults, logger=logger, loglevel=loglevel)
@@ -282,7 +282,7 @@ class X2GoXServer(threading.Thread):
         """
         if _X2GOCLIENT_OS not in ("Windows"):
             import exceptions
-            class OSNotSupportedException(exceptions.StandardError): pass
+            class OSNotSupportedException(exceptions.Exception): pass
             raise OSNotSupportedException('classes of x2go.xserver module are for Windows only')
 
         if logger is None:
@@ -297,7 +297,7 @@ class X2GoXServer(threading.Thread):
         self.xserver_config = xserver_config
         self.hProcess = None
 
-        if self.xserver_config.has_key('last_display'):
+        if 'last_display' in self.xserver_config:
 
             self.logger('setting DISPLAY environment variable to %s' % self.xserver_config['last_display'], loglevel=log.loglevel_NOTICE)
             os.environ.update({'DISPLAY': str(self.xserver_config['last_display'])})

--
Alioth's /srv/git/code.x2go.org/python-x2go.git//..//_hooks_/post-receive-email on /srv/git/code.x2go.org/python-x2go.git


More information about the x2go-commits mailing list