Blob Blame History Raw
diff -up winpdb-WINPDB_1_5_0/setup.py.dev5 winpdb-WINPDB_1_5_0/setup.py
--- winpdb-WINPDB_1_5_0/setup.py.dev5	2018-03-30 08:34:07.000000000 -0400
+++ winpdb-WINPDB_1_5_0/setup.py	2019-08-15 13:48:27.575840068 -0400
@@ -25,15 +25,17 @@
 
 from setuptools import setup
 
-import os
+import os, re
 
 # strip out build status
 LONG_DESC = ''.join( open('README.rst').readlines()[1:-8] )
 
+WINPDB_VERSION = re.search( r'WINPDB_VERSION\s*=\s*"(.*)"', open('winpdb.py').read() ).group(1).replace('-alpha', 'a')
+print( 'Packaging winpdb version: "%s"' % WINPDB_VERSION )
 
 setup(
     name = 'winpdb-reborn',
-    version = '1.5.0',
+    version = WINPDB_VERSION,
     description = 'A platform independent GPL Python debugger.',
     long_description = LONG_DESC,
     author = 'Philippe Fremy, Nir Aides',
@@ -45,7 +47,9 @@ setup(
         # How mature is this project? Common values are
         #   3 - Alpha
         #   4 - Beta
-        'Development Status :: 5 - Production/Stable',
+        #   5 - Production/Stable',
+        'Development Status :: 3 - Alpha',
+        # 'Development Status :: 5 - Production/Stable',
 
         # Runs in different environments
         'Environment :: Console',
@@ -62,7 +66,7 @@ setup(
         'Operating System :: POSIX',
 
         # This version is for python 2 only
-        'Programming Language :: Python :: 2 :: Only',
+        'Programming Language :: Python :: 3 :: Only',
 
 
         'Topic :: Software Development :: Debuggers',
@@ -83,7 +87,8 @@ setup(
         'Tracker': 'https://github.com/bluebird75/winpdb/issues',
     },
 
-    python_requires='>=2.6,  <3',
+    python_requires='>=3.4',
+    install_requires='wxpython>=4',
     py_modules = ['winpdb', 'rpdb2'],
 
     entry_points={
diff -up winpdb-WINPDB_1_5_0/winpdb.py.dev5 winpdb-WINPDB_1_5_0/winpdb.py
--- winpdb-WINPDB_1_5_0/winpdb.py.dev5	2018-03-30 08:34:07.000000000 -0400
+++ winpdb-WINPDB_1_5_0/winpdb.py	2019-08-15 13:48:24.183909002 -0400
@@ -1,4 +1,5 @@
 #! /usr/bin/env python
+# -*- coding: utf-8 -*-
 
 """
     winpdb.py
@@ -23,7 +24,12 @@
     51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA    
 """
 
-ABOUT_NOTICE = """*Winpdb Reborn* 1.5 is a platform independent lightweight
+VERSION = (2, 0, 0, 5, 'Tychod')
+WINPDB_VERSION = "2.0.0.dev5"
+WINPDB_TITLE = "Winpdb Reborn %s" % WINPDB_VERSION
+RPDB2_EXPECTED_VERSION = 'RPDB_1_5_0'
+
+ABOUT_NOTICE = """*Winpdb Reborn* %s is a platform independent lightweight
 standalone graphical debugger for Python 2 and 3. It supports
 conditional breakpoints, multi-threaded debugging, smart 
 handling of forks, remote debugging and more.
@@ -43,7 +49,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICU
 See the GNU General Public License for more details.
 
 Credits:
-Work on version 1.4.8 was sponsored by Investortools, Inc."""
+Work on version 1.4.8 was sponsored by Investortools, Inc.""" % WINPDB_VERSION
 
 LICENSE_NOTICE = """
 This program is free software; you can redistribute it and/or modify it 
@@ -279,15 +285,15 @@ END OF TERMS AND CONDITIONS
 
 import sys
 
-WXVER_PYTHON2 = "3"
-WXVER_PYTHON3 = "4"
+# Winpdb Works only with WxPython 4, compatible with python 3.4+
+MIN_WXVER = "4.0.0"
 
 STR_BAD_PYTHON_ERROR_TITLE = 'Winpdb Error'
 STR_BAD_PYTHON_ERROR_MSG = """Unsupported Python version
 Winpdb does not run with this version of Python. You need
-Python 2.6 or 2.7 with WxPython 3 from sourceforge to run Winpdb.
+Python 2.6 or above with at least WxPython 3 to run Winpdb.
 
-To debug a program written for PyPy, launch
+To debug a program written for PyPy or Python 3.x , launch
 Winpdb with Python 2 and select the interpreter to use in 
 the launch dialog.
 
@@ -296,12 +302,9 @@ of Python."""
 
 STR_WXPYTHON_ERROR_TITLE = 'Winpdb Error'
 STR_WXPYTHON_ERROR_MSG = """wxPython was not found.
-wxPython 3 is required to run the winpdb GUI. 
-Download it from sourceforge: https://sourceforge.net/projects/wxpython/files/wxPython/
-
-Note that wxPython 4 only support Python 3 and above. There is a dedicated version
-of winpdb-reborn for Python 3 and wxPython 4.
-
+wxPython 4.0 or higher is required to run the Winpdb GUI.
+wxPython is the graphical user interface toolkit used by Winpdb.
+You can find more information on wxPython at http://www.wxpython.org/
 To use the debugger without a GUI, run rpdb2."""
 
 STR_X_ERROR_MSG = """It was not possible to start Winpdb. 
@@ -336,38 +339,30 @@ def myErrorMsgDialog(title, msg):
 RUNNING_UNDER_PY2 = (sys.version_info[0] == 2)
 RUNNING_UNDER_PY3 = (sys.version_info[0] == 3)
 
-if platform.python_implementation()  != 'CPython' or RUNNING_UNDER_PY3:
+if RUNNING_UNDER_PY2 == RUNNING_UNDER_PY3:
+    # Houston, we have a problem!
+    raise ValueError('XXX')
+
+if platform.python_implementation()  != 'CPython':
     # Only CPython 2.x and 3.x supported
     myErrorMsgDialog( STR_BAD_PYTHON_ERROR_TITLE, STR_BAD_PYTHON_ERROR_MSG )
     sys.exit(1)
 
 
-if RUNNING_UNDER_PY2:
-    if 'wx' not in sys.modules and 'wxPython' not in sys.modules:
-        # multi-install of Wx, correct version must be selected with wxversion
-        try:
-            import wxversion
-        except ImportError:
-            rpdb2._print(STR_WXPYTHON_ERROR_MSG, sys.__stderr__)
-            myErrorMsgDialog( STR_WXPYTHON_ERROR_TITLE, STR_WXPYTHON_ERROR_MSG )
-            sys.exit(1)
-
-        global WXVER
-        if RUNNING_UNDER_PY2:
-            WXVER = WXVER_PYTHON2
-        else:
-            WXVER = WXVER_PYTHON3
-        wxversion.ensureMinimal(WXVER)
-else:
-    myErrorMsgDialog( STR_BAD_PYTHON_ERROR_TITLE, STR_BAD_PYTHON_ERROR_MSG )
+try:
+    import wx
+except ImportError:
+    rpdb2._print(STR_WXPYTHON_ERROR_MSG, sys.__stderr__)
+    myErrorMsgDialog( STR_WXPYTHON_ERROR_TITLE, STR_WXPYTHON_ERROR_MSG )
     sys.exit(1)
 
-import wx
-
-assert wx.VERSION_STRING >= WXVER
+assert wx.VERSION_STRING >= MIN_WXVER
         
 import wx.lib.wxpTag
-import wx.gizmos as wx_dataview_or_gizmos
+if RUNNING_UNDER_PY3:
+    import wx.dataview as wx_dataview_or_gizmos
+else:
+    import wx.gizmos as wx_dataview_or_gizmos
 
 import wx.html
 
@@ -378,8 +373,12 @@ import wx.stc as stc
 
 import webbrowser
 import traceback
-from cStringIO import StringIO
-import Queue
+if RUNNING_UNDER_PY2:
+    from cStringIO import StringIO
+    from Queue import Queue
+else:
+    from io import StringIO
+    from queue import Queue
 
 import threading
 import tempfile
@@ -543,10 +542,6 @@ TLC_HEADER_NAME = "Name"
 TLC_HEADER_REPR = "Repr"
 TLC_HEADER_TYPE = "Type"
 
-VERSION = (1, 5, 0, 0, 'Tychod')
-WINPDB_TITLE = "Winpdb Reborn 1.5.0"
-WINPDB_VERSION = "WINPDB_REBORN_1_5_0"
-
 WINPDB_SIZE = "winpdb_size"
 WINPDB_MAXIMIZE = "winpdb_maximize"
 SPLITTER_1_POS = "splitter_1_pos"
@@ -568,7 +563,14 @@ WINPDB_SETTINGS_DEFAULT = {
 }
 
 AC_CHAR = "\t"
-AC_EXIT = "Alt-X"
+AC_PWD = "Ctrl-P"
+AC_LAUNCH = "Ctrl-L"
+AC_ATTACH = "Ctrl-A"
+AC_DETACH = "Ctrl-D"
+AC_STOP = "Ctrl-S"
+AC_RESTART = "Ctrl-R"
+AC_OPEN = "Ctrl-O"
+AC_EXIT = "Ctrl-Q"
 AC_ANALYZE = "F3"
 AC_BREAK = "F4"
 AC_GO = "F5"
@@ -583,13 +585,13 @@ ML_SEPARATOR = "<separator>"
 ML_ROOT = "<root>"
 
 ML_FILE = "&File"
-ML_PWD = "&Password"
-ML_LAUNCH = "&Launch"
-ML_ATTACH = "&Attach"
-ML_DETACH = "&Detach"
-ML_STOP = "&Stop"
-ML_RESTART = "&Restart"
-ML_OPEN = "&Open Source"
+ML_PWD = "&Password" + AC_CHAR + AC_PWD
+ML_LAUNCH = "&Launch" + AC_CHAR + AC_LAUNCH
+ML_ATTACH = "&Attach" + AC_CHAR + AC_ATTACH
+ML_DETACH = "&Detach" + AC_CHAR + AC_DETACH
+ML_STOP = "&Stop" + AC_CHAR + AC_STOP
+ML_RESTART = "&Restart" + AC_CHAR + AC_RESTART
+ML_OPEN = "&Open Source" + AC_CHAR + AC_OPEN
 ML_EXIT = "E&xit" + AC_CHAR + AC_EXIT
 
 ML_BREAKPOINTS = "&Breakpoints"
@@ -758,7 +760,7 @@ ABOUT_HTML_SUFFIX = """
 
 WEBSITE_URL  = "https://github.com/bluebird75/winpdb"
 SUPPORT_URL  = "https://github.com/bluebird75/winpdb/issues"
-DOCS_URL     = "http://www.winpdb.org/?page_id=5"
+DOCS_URL = "http://www.winpdb.org/?page_id=5"
 EXT_DOCS_URL = "http://www.winpdb.org/?page_id=17"
 UPDATES_URL  = "https://github.com/bluebird75/winpdb"
 
@@ -833,13 +835,13 @@ def open_new(url):
     webbrowser.open_new(url) 
 
 
+from io import BytesIO
 
 def image_from_base64(str_b64):
     b = rpdb2.as_bytes(str_b64)
-    s = base64.decodestring(b)
-    stream = StringIO(s)
-    image = wx.ImageFromStream(stream)
-
+    s = base64.decodebytes(b)
+    stream = BytesIO(s)
+    image = wx.Image(stream)
     return image
 
     
@@ -915,8 +917,8 @@ class CMenuBar:
         self.m_cascades = {}
         
     def init_menubar(self, resource):
-        if 'wxMac' in wx.PlatformInfo:
-             wx.MenuBar.SetAutoWindowMenu(False)
+        # if 'wxMac' in wx.PlatformInfo:
+        #      wx.MenuBar.SetAutoWindowMenu(False)
 
         self.m_menubar = wx.MenuBar()
 
@@ -936,7 +938,7 @@ class CMenuBar:
                     if parent_label == ML_ROOT:
                         parent.Append(child, e)
                     else:
-                        parent.AppendMenu(wx.NewId(), e, child)
+                        parent.AppendMenu(wx.ID_ANY, e, child)
                         self.m_encapsulating_menu_items[e] = parent
 
                     self.m_cascades[e] = child
@@ -976,7 +978,7 @@ class CMenuBar:
 
     def add_menu_item(self, menu_label, item_label, command):
         if not g_fUnicode:
-            item_label = rpdb2.as_string(item_label, wx.GetDefaultPyEncoding())
+            item_label = rpdb2.as_string(item_label)
 
         parent = self.m_cascades[menu_label]
         item = parent.Append(-1, item_label)
@@ -987,7 +989,7 @@ class CMenuBar:
 
         while parent.GetMenuItemCount() > 0:
             i = parent.FindItemByPosition(0)
-            parent.DeleteItem(i)
+            parent.DestroyItem(i)
 
         
 
@@ -1009,30 +1011,32 @@ class CToolBar:
                 continue
 
             command = e[COMMAND]
-            id = wx.NewId()
+            id = wx.Window.NewControlId()
 
             if TEXT in e:
                 button = wx.Button(self.m_toolbar, id, e[TEXT], style = wx.NO_BORDER)
-                button.SetToolTipString(item_label)
+                button.SetToolTip(item_label)
                 self.m_toolbar.AddControl(button)
                 self.m_items[item_label] = {ID: id}
-                wx.EVT_BUTTON(self.m_toolbar, id, command)
+                # wx.EVT_BUTTON(self.m_toolbar, id, command)
+                self.Bind( wx.EVT_BUTTON, command, id = id)
                 continue
 
             if DATA in e:
                 image = image_from_base64(e[DATA])
-                bitmap = wx.BitmapFromImage(image)
+                bitmap = wx.Bitmap(image)
 
             if DATA2 in e:
                 image2 = image_from_base64(e[DATA2])
-                bitmap2 = wx.BitmapFromImage(image2)
-                self.m_toolbar.AddSimpleTool(id, bitmap, item_label, isToggle = True)
+                bitmap2 = wx.Bitmap(image2)
+                self.m_toolbar.AddTool(id, '', bitmap, wx.NullBitmap, wx.ITEM_CHECK, item_label, '' )
+
                 self.m_items[item_label] = {ID: id, DATA: bitmap, DATA2: bitmap2}
                 self.Bind(wx.EVT_TOOL, command, id = id)
                 self.Bind(wx.EVT_TOOL, self.OnToggleTool, id = id)
 
             else:
-                self.m_toolbar.AddSimpleTool(id, bitmap, item_label)
+                self.m_toolbar.AddTool(id, '', bitmap, wx.NullBitmap, wx.ITEM_NORMAL, item_label )
                 self.m_items[item_label] = {ID: id}
                 self.Bind(wx.EVT_TOOL, command, id = id)
             
@@ -1123,7 +1127,7 @@ class CStatusBar:
         self.m_formats = [e.get(FORMAT, "") for e in resource]
         self.m_keys = [e.get(KEYS, []) for e in resource]
         
-        self.m_statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP)
+        self.m_statusbar = self.CreateStatusBar(1, wx.STB_SIZEGRIP)
         self.m_statusbar.SetFieldsCount(len(self.m_widths))
         self.m_statusbar.SetStatusWidths(self.m_widths)
         
@@ -1150,7 +1154,7 @@ class CStatusBar:
                 return
                 
             image = image_from_base64(data)
-            bitmap = wx.BitmapFromImage(image)
+            bitmap = wx.Bitmap(image)
             p = wx.Panel(self.m_statusbar)
             sb = wx.StaticBitmap(p, -1, bitmap)
 
@@ -1161,7 +1165,7 @@ class CStatusBar:
                 self.m_bitmaps[i][0].Hide()
             else:
                 image = image_from_base64(data)
-                bitmap = wx.BitmapFromImage(image)
+                bitmap = wx.Bitmap(image)
                 
                 self.m_bitmaps[i][1].SetBitmap(bitmap)
                 self.m_bitmaps[i][0].Show()
@@ -1175,8 +1179,8 @@ class CStatusBar:
             p.SetPosition((rect.x + 2, rect.y + 2))
             s = sb.GetSize()
             sb.SetSize((s[0], rect.height - 4))
-            sb.SetToolTipString(tooltip)
-            p.SetToolTipString(tooltip)
+            sb.SetToolTip(tooltip)
+            p.SetToolTip(tooltip)
             p.SetClientSize(sb.GetSize())
             
         self.sizeChanged = False
@@ -1266,7 +1270,7 @@ class CJobs:
 
 
     def set_cursor(self, id):
-        cursor = wx.StockCursor(id)
+        cursor = wx.Cursor(id)
         self.SetCursor(cursor)        
         
 
@@ -1379,19 +1383,16 @@ class CWinpdbWindow(wx.Frame, CMainWindo
             self.SetLayoutDirection(1)
         
         image = image_from_base64(BASE64_ICON_16)
-        bitmap = wx.BitmapFromImage(image)
-        icon16 = wx.EmptyIcon()
-        icon16.CopyFromBitmap(bitmap)
+        bitmap = wx.Bitmap(image)
+        icon16 = wx.Icon(bitmap)
 
         image = image_from_base64(BASE64_ICON_32)
-        bitmap = wx.BitmapFromImage(image)
-        icon32 = wx.EmptyIcon()
-        icon32.CopyFromBitmap(bitmap)
+        bitmap = wx.Bitmap(image)
+        icon32 = wx.Icon(bitmap)
 
         image = image_from_base64(BASE64_ICON_64)
-        bitmap = wx.BitmapFromImage(image)
-        icon64 = wx.EmptyIcon()
-        icon64.CopyFromBitmap(bitmap)
+        bitmap = wx.Bitmap(image)
+        icon64 = wx.Icon(bitmap)
 
         ibundle = wx.IconBundle()
         ibundle.AddIcon(icon16)
@@ -1522,7 +1523,7 @@ class CWinpdbWindow(wx.Frame, CMainWindo
         
         self.m_code_viewer = CCodeViewer(self.m_splitterh3, style = wx.NO_BORDER | wx.TAB_TRAVERSAL, session_manager = self.m_session_manager, source_manager = self.m_source_manager, notify_filename = self.do_notify_filename)        
 
-        self.m_console = CConsole(self.m_splitterh3, style = wx.NO_BORDER | wx.TAB_TRAVERSAL, session_manager = self.m_session_manager, exit_command = self.do_exit)
+        self.m_console = CConsole(self.m_splitterh3, style = wx.NO_BORDER | wx.TAB_TRAVERSAL, session_manager = self.m_session_manager, exit_command = self.do_exit, name = 'console')
         
         self.m_splitterh2.SplitHorizontally(self.m_namespace_viewer, self.m_threads_viewer)
         self.m_splitterh1.SplitHorizontally(self.m_splitterh2, self.m_stack_viewer)
@@ -1680,7 +1681,7 @@ class CWinpdbWindow(wx.Frame, CMainWindo
     #
     
     def OnFrameSelected(self, event):    
-        self.m_async_sm.set_frame_index(event.m_itemIndex)
+        self.m_async_sm.set_frame_index(event.Index)
         
 
     def update_frame(self, event):
@@ -1697,11 +1698,17 @@ class CWinpdbWindow(wx.Frame, CMainWindo
     #
     
     def update_stack(self, event):
+        '''Arguments:
+        - event: a CEventStack, containing a list of thread debugging states
+        '''
         self.m_stack = event.m_stack
         wx.CallAfter(self.do_update_stack, event.m_stack)
 
 
     def do_update_stack(self, _stack):
+        '''Arguments:
+        _stack: list of thread debugging states
+        '''
         self.m_stack = _stack
 
         self.m_stack_viewer.update_stack_list(self.m_stack)
@@ -1812,7 +1819,7 @@ class CWinpdbWindow(wx.Frame, CMainWindo
     def notify_conflicting_modules(self, event):
         s = ', '.join(event.m_modules_list)
         if not g_fUnicode:
-            s = rpdb2.as_string(s, wx.GetDefaultPyEncoding())
+            s = rpdb2.as_string(s)
 
         dlg = wx.MessageDialog(self, rpdb2.STR_CONFLICTING_MODULES % s, MSG_WARNING_TITLE, wx.OK | wx.ICON_WARNING)
         dlg.ShowModal()
@@ -1883,7 +1890,7 @@ class CWinpdbWindow(wx.Frame, CMainWindo
 
 
     def set_cursor(self, id):
-        cursor = wx.StockCursor(id)
+        cursor = wx.Cursor(id)
         self.SetCursor(cursor)        
         self.m_code_viewer.set_cursor(id)        
         self.m_threads_viewer.set_cursor(id)        
@@ -2269,7 +2276,7 @@ class CWinpdbApp(wx.App):
 
     def OnExit(self):
         self.m_settings.save_settings()
-        
+        return super().OnExit()
 
 
 class CCaption(wx.Panel):
@@ -2278,8 +2285,8 @@ class CCaption(wx.Panel):
         
         wx.Panel.__init__(self, *args, **kwargs)
 
-        self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_INACTIVECAPTION))
-        self.SetForegroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_CAPTIONTEXT))
+        self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INACTIVECAPTION))
+        self.SetForegroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_CAPTIONTEXT))
         
         sizerv = wx.BoxSizer(wx.VERTICAL)
 
@@ -2287,7 +2294,7 @@ class CCaption(wx.Panel):
         sizerv.Add(self.m_static_text, 0, wx.EXPAND | wx.ALL, 2)
 
         font = self.m_static_text.GetFont()
-        new_font = wx.Font(pointSize = font.GetPointSize(), family = font.GetFamily(), style = font.GetStyle(), weight = wx.BOLD, face = font.GetFaceName())
+        new_font = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(), wx.BOLD, font.GetUnderlined(), font.GetFaceName())
         self.m_static_text.SetFont(new_font)
 
         self.SetSizer(sizerv)
@@ -2305,7 +2312,7 @@ class CCaptionManager:
     def OnGainFocus(self, event):        
         self.m_n_focus += 1
         
-        self.m_caption.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION))
+        self.m_caption.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION))
         self.m_caption.Refresh()
         event.Skip()
 
@@ -2317,11 +2324,9 @@ class CCaptionManager:
         #
         # Event may get sent after the object has been deleted.
         #
-        try:
-            self.m_caption.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_INACTIVECAPTION))
+        if self.m_caption:
+            self.m_caption.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INACTIVECAPTION))
             self.m_caption.Refresh()
-        except wx.PyDeadObjectError:
-            pass
 
         event.Skip()
 
@@ -2445,6 +2450,20 @@ class CStyledViewer(stc.StyledTextCtrl):
             self.GetParent().GetEventHandler().ProcessEvent(ne)
             event.Skip()
             return
+        elif key_code == 74: # J
+            (_, col_no, line_no) = self.PositionToXY(self.GetInsertionPoint())
+            console = wx.FindWindowByName('console')
+            value = rpdb2.as_unicode('jump %s' % (line_no + 1))
+            console.m_queue.put(value + '\n')
+        elif key_code == 86: # V
+            value = self.GetSelectedText()
+            if value:
+                value = 'eval ' + value
+                console = wx.FindWindowByName('console')
+                console.m_console_out.AppendText(CONSOLE_PROMPT + value + '\n')
+                # console.set_history(value)
+                value = rpdb2.as_unicode(value)
+                console.m_queue.put(value + '\n')
             
         event.Skip()
 
@@ -2513,9 +2532,9 @@ class CSourceManager:
             _time = 0
             _filename = r[rpdb2.DICT_KEY_FILENAME]
             source_lines = r[rpdb2.DICT_KEY_LINES]
-            source = string.join(source_lines, '')
+            source = ''.join(source_lines)
             if not g_fUnicode:
-                source = rpdb2.as_string(source, wx.GetDefaultPyEncoding())
+                source = rpdb2.as_string(source)
         
         elif t == rpdb2.NotPythonSource and fComplain:
             dlg = wx.MessageDialog(None, MSG_ERROR_FILE_NOT_PYTHON % (filename, ), MSG_WARNING_TITLE, wx.OK | wx.ICON_WARNING)
@@ -2539,7 +2558,7 @@ class CSourceManager:
             _filename = filename
             source = STR_FILE_LOAD_ERROR2 % (filename, )
             if not g_fUnicode:
-                source = rpdb2.as_string(source, wx.GetDefaultPyEncoding())
+                source = rpdb2.as_string(source)
         
         else:
             rpdb2.print_debug('get_source_file() returned the following error: %s' % repr(t))
@@ -2548,7 +2567,7 @@ class CSourceManager:
             _filename = filename
             source = STR_FILE_LOAD_ERROR2 % (filename, )
             if not g_fUnicode:
-                source = rpdb2.as_string(source, wx.GetDefaultPyEncoding())
+                source = rpdb2.as_string(source)
                     
         try:    
             self.m_lock.acquire()
@@ -2796,7 +2815,7 @@ class CCodeViewer(wx.Panel, CJobs, CCapt
       
         displayed_filename = _filename
         if not g_fUnicode:
-            displayed_filename = rpdb2.as_string(displayed_filename, wx.GetDefaultPyEncoding())
+            displayed_filename = rpdb2.as_string(displayed_filename)
 
         label = CAPTION_SOURCE + ' ' + rpdb2.clip_filename(displayed_filename)
         self.m_caption.m_static_text.SetLabel(label)
@@ -2839,7 +2858,7 @@ class CCodeViewer(wx.Panel, CJobs, CCapt
         
         displayed_filename = filename
         if not g_fUnicode:
-            displayed_filename = rpdb2.as_string(displayed_filename, wx.GetDefaultPyEncoding())
+            displayed_filename = rpdb2.as_string(displayed_filename)
 
         label = CAPTION_SOURCE + ' ' + rpdb2.clip_filename(displayed_filename)
         self.m_caption.m_static_text.SetLabel(label)
@@ -2932,7 +2951,7 @@ class CConsole(wx.Panel, CCaptionManager
         
         self.m_console = rpdb2.CConsole(self.m_session_manager, stdin = self, stdout = self, fSplit = True)
 
-        self.m_queue = Queue.Queue()
+        self.m_queue = Queue()
         
         _sizerv = wx.BoxSizer(wx.VERTICAL)
         sizerv = wx.BoxSizer(wx.VERTICAL)
@@ -2968,17 +2987,18 @@ class CConsole(wx.Panel, CCaptionManager
     def OnConsoleOutKeyPressed(self, event):
         key_code = event.GetKeyCode()
 
-        if key_code != wx.WXK_TAB:
-            return
-            
-        forward = not event.ShiftDown()            
-        ne = wx.NavigationKeyEvent()
-        ne.SetDirection(forward)
-        ne.SetCurrentFocus(self.m_console_out)
-        ne.SetEventObject(self.m_console_out)
-        self.GetEventHandler().ProcessEvent(ne)
+        if key_code == wx.WXK_TAB:
+            forward = not event.ShiftDown()            
+            ne = wx.NavigationKeyEvent()
+            ne.SetDirection(forward)
+            ne.SetCurrentFocus(self.m_console_out)
+            ne.SetEventObject(self.m_console_out)
+            self.GetEventHandler().ProcessEvent(ne)
 
-        event.Skip()
+            event.Skip()
+
+        elif (key_code == 67) and event.ControlDown(): # Ctrl+C
+            value = self.m_console_out.Copy()
     
 
     def set_focus(self):
@@ -2999,7 +3019,7 @@ class CConsole(wx.Panel, CCaptionManager
             face = "Courier"
             point_size = font.GetPointSize()
             
-        new_font = wx.Font(pointSize = point_size, family = font.GetFamily(), style = font.GetStyle(), weight = font.GetWeight(), face = face)
+        new_font = wx.Font(point_size, font.GetFamily(), font.GetStyle(), font.GetWeight(), font.GetUnderlined(), face)
         ctrl.SetFont(new_font)
 
         
@@ -3016,7 +3036,7 @@ class CConsole(wx.Panel, CCaptionManager
 
     def write(self, _str):
         if not g_fUnicode:
-            _str = rpdb2.as_string(_str, wx.GetDefaultPyEncoding())
+            _str = rpdb2.as_string(_str)
         else:
             _str = rpdb2.as_unicode(_str, self.encoding)
 
@@ -3031,7 +3051,7 @@ class CConsole(wx.Panel, CCaptionManager
                 if len(s) == 0:
                     break
             
-        wx.CallAfter(self.m_console_out.write, _str[1:])    
+        wx.CallAfter(self.m_console_out.AppendText, _str[1:])    
 
 
     def flush(self):
@@ -3092,7 +3112,7 @@ class CConsole(wx.Panel, CCaptionManager
             return
 
         if len(completions) > COMPLETIONS_WARNING_THRESHOLD and not fForce:
-            self.m_console_out.write(COMPLETIONS_WARNING % len(completions))
+            self.m_console_out.AppendText(COMPLETIONS_WARNING % len(completions))
             self.m_fcompletions_warning = True
             return
 
@@ -3122,7 +3142,7 @@ class CConsole(wx.Panel, CCaptionManager
         lines = textwrap.wrap(out, 60)
         text = '\n'.join(lines) + '\n'
 
-        self.m_console_out.write(CONSOLE_COMPLETIONS % text)
+        self.m_console_out.AppendText(CONSOLE_COMPLETIONS % text)
 
         
     def OnSendText(self, event):
@@ -3131,14 +3151,14 @@ class CConsole(wx.Panel, CCaptionManager
         value = self.m_console_in.GetValue()
         self.set_history(value)
 
-        self.m_console_out.write(CONSOLE_PROMPT + value + '\n') 
+        self.m_console_out.AppendText(CONSOLE_PROMPT + value + '\n') 
         self.m_console_in.Clear()
 
         if value in ['exit', 'EOF']:
             self.m_exit_command()
             return
 
-        value = rpdb2.as_unicode(value, wx.GetDefaultPyEncoding())
+        value = rpdb2.as_unicode(value)
         
         self.m_queue.put(value + '\n')
 
@@ -3263,7 +3283,7 @@ class CThreadsViewer(wx.Panel, CCaptionM
 
 
     def set_cursor(self, id):
-        cursor = wx.StockCursor(id)
+        cursor = wx.Cursor(id)
         self.SetCursor(cursor)        
         self.m_threads.SetCursor(cursor)        
 
@@ -3293,10 +3313,10 @@ class CThreadsViewer(wx.Panel, CCaptionM
             return -1
 
         if not g_fUnicode:
-            thread_name = rpdb2.as_string(thread_name, wx.GetDefaultPyEncoding())
+            thread_name = rpdb2.as_string(thread_name)
 
-        self.m_threads.SetStringItem(index, 1, thread_name)
-        self.m_threads.SetStringItem(index, 2, [rpdb2.STATE_RUNNING, rpdb2.STR_STATE_BROKEN][fBroken])
+        self.m_threads.SetItem(index, 1, thread_name)
+        self.m_threads.SetItem(index, 2, [rpdb2.STATE_RUNNING, rpdb2.STR_STATE_BROKEN][fBroken])
 
         return index
 
@@ -3313,12 +3333,12 @@ class CThreadsViewer(wx.Panel, CCaptionM
             tid = s[rpdb2.DICT_KEY_TID]
             name = s[rpdb2.DICT_KEY_NAME]
             if not g_fUnicode:
-                name = rpdb2.as_string(name, wx.GetDefaultPyEncoding())
+                name = rpdb2.as_string(name)
 
             fBroken = s[rpdb2.DICT_KEY_BROKEN]
-            index = self.m_threads.InsertStringItem(sys.maxint, repr(tid))
-            self.m_threads.SetStringItem(index, 1, name)
-            self.m_threads.SetStringItem(index, 2, [rpdb2.STATE_RUNNING, rpdb2.STR_STATE_BROKEN][fBroken])
+            index = self.m_threads.InsertItem( i, repr(tid))
+            self.m_threads.SetItem(index, 1, name)
+            self.m_threads.SetItem(index, 2, [rpdb2.STATE_RUNNING, rpdb2.STR_STATE_BROKEN][fBroken])
             self.m_threads.SetItemData(index, tid)
             if tid == current_thread:
                 j = i
@@ -3333,7 +3353,7 @@ class CThreadsViewer(wx.Panel, CCaptionM
     def OnThreadSelected(self, event):                
         if self.m_suppress_recursion == 0:
             self.m_suppress_recursion += 1
-            index = event.m_itemIndex
+            index = event.Index
             tid = self.m_threads.GetItemData(index)
             self.m_select_command(tid)
         else:
@@ -3341,7 +3361,35 @@ class CThreadsViewer(wx.Panel, CCaptionM
 
         event.Skip()
 
+gItemsWithChildren = {}
+
+# Support function for the porting to WxPython 4
+def ItemHasChildren(tree, item):
+    '''Return True if the _item_ of TreeListCtrl has children.'''
+    if item in gItemsWithChildren:
+        return gItemsWithChildren[item]
+
+    firstChild = tree.GetFirstChild(item)
+    if firstChild and firstChild.IsOk():
+        print('ItemHasChildren( %s) -> True' % (ItemToStr(tree, item)))
+        return True
+
+    print('ItemHasChildren( %s) -> False' % (ItemToStr(tree, item)))
+    return False
 
+def SetItemHasChildren(tree, item, state):
+    '''Stub function, not available in WxPython 4.
+    It used to display an expand symbol depending on _state_ so that the
+    children list can be lazily expanded.'''
+    print('SetItemHasChildren( %s, %s)' % (ItemToStr(tree, item), state ))
+    gItemsWithChildren[item] = state
+    pass
+
+def ItemToStr(tree, item):
+    s = 'Item<"%s","%s",%s>' % (tree.GetItemText(item,1), tree.GetItemText(item,2), tree.GetItemData(item))
+    return s
+
+import pprint
         
 class CNamespacePanel(wx.Panel, CJobs):
     def __init__(self, *args, **kwargs):
@@ -3363,14 +3411,14 @@ class CNamespacePanel(wx.Panel, CJobs):
 
         sizerv = wx.BoxSizer(wx.VERTICAL)
         
-        self.m_tree = wx_dataview_or_gizmos.TreeListCtrl(self, -1, style = wx.TR_HIDE_ROOT | wx.TR_DEFAULT_STYLE | wx.TR_FULL_ROW_HIGHLIGHT | wx.NO_BORDER)
+        self.m_tree = wx_dataview_or_gizmos.TreeListCtrl(self, -1 ) # note: default style is perfect for us
 
-        self.m_tree.AddColumn(TLC_HEADER_NAME)
-        self.m_tree.AddColumn(TLC_HEADER_TYPE)
-        self.m_tree.AddColumn(TLC_HEADER_REPR)
+        self.m_tree.AppendColumn(TLC_HEADER_NAME)
+        self.m_tree.AppendColumn(TLC_HEADER_TYPE)
+        self.m_tree.AppendColumn(TLC_HEADER_REPR)
         self.m_tree.SetColumnWidth(2, 800)
-        self.m_tree.SetMainColumn(0) 
-        self.m_tree.SetLineSpacing(0)
+        self.m_tree.SetSortColumn(0) 
+        # self.m_tree.SetLineSpacing(0)
         
         self.m_tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding)
         self.m_tree.Bind(wx.EVT_TREE_ITEM_COLLAPSING, self.OnItemCollapsing)
@@ -3401,13 +3449,14 @@ class CNamespacePanel(wx.Panel, CJobs):
 
         
     def bind_caption(self, caption_manager):
-        w = self.m_tree.GetMainWindow()
+        # w = self.m_tree.GetMainWindow()
+        w = self.m_tree.GetView()
         caption_manager.bind_caption(w)
 
         
     def OnItemActivated(self, event):
         item = event.GetItem()
-        (expr, is_valid) = self.m_tree.GetPyData(item)
+        (expr, is_valid) = self.m_tree.GetItemData(item)
         if expr in [STR_NAMESPACE_LOADING, STR_NAMESPACE_DEADLOCK, rpdb2.STR_MAX_NAMESPACE_WARNING_TITLE]:
             return
 
@@ -3434,6 +3483,7 @@ class CNamespacePanel(wx.Panel, CJobs):
 
 
     def callback_execute(self, r, exc_info):
+        print('callback_execute(%s, %s)'  % (r, exc_info) )
         (t, v, tb) = exc_info
 
         if t != None:
@@ -3470,30 +3520,51 @@ class CNamespacePanel(wx.Panel, CJobs):
 
 
     def GetChildrenCount(self, item):
-        n = self.m_tree.GetChildrenCount(item)
-        if n != 1:
-            return n 
+        # n = self.m_tree.GetChildrenCount(item)
+        # n = self.m_tree.GetItemCount(item)
+        # if n != 1:
+        #    print('GetChildrenCount(item=%s) -> %d' % (ItemToStr(self.m_tree, item), n) )
+        #    return n
+
+        children = self.get_children(item)
+        if len(children) == 0 or len(children) > 1:
+            return len(children)
 
-        child = self.get_children(item)[0]
-        (expr, is_valid) = self.m_tree.GetPyData(child)
+        child = children[0]
+        (expr, is_valid) = self.m_tree.GetItemData(child)
 
         if expr in [STR_NAMESPACE_LOADING, STR_NAMESPACE_DEADLOCK]:
+            print('GetChildrenCount(item=%s) -> %d' % (ItemToStr(self.m_tree, item), 0) )
             return 0
 
+        print('GetChildrenCount(item=%s) -> %d' % (ItemToStr(self.m_tree, item), 1))
         return 1
         
         
     def expand_item(self, item, _map, froot = False, fskip_expansion_check = False):
-        if not self.m_tree.ItemHasChildren(item):
+        '''Arguments:
+        :param item: python expression
+        :param _map: list of dictionnary of expression content, see CSessionManager.get_namespace() for details
+        :param froot: boolen, True if it is the root item
+        :param fskip_expansion_check:
+        :return:
+        '''
+        print('expand_item(item=%s, _map=%s, froot=%s, fskip_expansion=%s)' %
+              (ItemToStr(self.m_tree, item), pprint.pformat(_map, 4), froot, fskip_expansion_check))
+        if not ItemHasChildren(self.m_tree, item):
+            print('expand_item() -> no action')
             return
         
+        # skip expansion if item is already expanded
         if not froot and not fskip_expansion_check and self.m_tree.IsExpanded(item):
+            print('expand_item() -> no action')
             return
 
         if self.GetChildrenCount(item) > 0:
+            print('expand_item() -> no action')
             return
         
-        (expr, is_valid) = self.m_tree.GetPyData(item)
+        (expr, is_valid) = self.m_tree.GetItemData(item)
 
         l = [e for e in _map if e.get(rpdb2.DICT_KEY_EXPR, None) == expr]
         if l == []:
@@ -3504,10 +3575,12 @@ class CNamespacePanel(wx.Panel, CJobs):
             return   
 
         if rpdb2.DICT_KEY_ERROR in _r:
+            print('expand_item() -> no action due to error')
             return
         
         if _r[rpdb2.DICT_KEY_N_SUBNODES] == 0:
-            self.m_tree.SetItemHasChildren(item, False)
+            print('expand_item() -> no subnodes, setting HasChildren to false')
+            SetItemHasChildren(self.m_tree, item, False)
             return
 
         #
@@ -3516,6 +3589,7 @@ class CNamespacePanel(wx.Panel, CJobs):
         # In case of a list, no sorting is needed.
         #
 
+        print('expand_item() -> filling subnodes, setting HasChildren to true & expand item')
         snl = _r[rpdb2.DICT_KEY_SUBNODES] 
        
         for r in snl:
@@ -3524,42 +3598,44 @@ class CNamespacePanel(wx.Panel, CJobs):
                 _type = r[rpdb2.DICT_KEY_TYPE]
                 _repr = r[rpdb2.DICT_KEY_REPR]
             else:
-                _name = rpdb2.as_string(r[rpdb2.DICT_KEY_NAME], wx.GetDefaultPyEncoding())
-                _type = rpdb2.as_string(r[rpdb2.DICT_KEY_TYPE], wx.GetDefaultPyEncoding())
-                _repr = rpdb2.as_string(r[rpdb2.DICT_KEY_REPR], wx.GetDefaultPyEncoding())
+                _name = rpdb2.as_string(r[rpdb2.DICT_KEY_NAME])
+                _type = rpdb2.as_string(r[rpdb2.DICT_KEY_TYPE])
+                _repr = rpdb2.as_string(r[rpdb2.DICT_KEY_REPR])
 
             identation = '' 
             #identation = ['', '  '][os.name == rpdb2.POSIX and r[rpdb2.DICT_KEY_N_SUBNODES] == 0]
 
             child = self.m_tree.AppendItem(item, identation + _name)
-            self.m_tree.SetItemText(child, ' ' + _repr, 2)
-            self.m_tree.SetItemText(child, ' ' + _type, 1)
-            self.m_tree.SetItemPyData(child, (r[rpdb2.DICT_KEY_EXPR], r[rpdb2.DICT_KEY_IS_VALID]))
-            self.m_tree.SetItemHasChildren(child, (r[rpdb2.DICT_KEY_N_SUBNODES] > 0))
+            self.m_tree.SetItemText(child, 2, ' ' + _repr)
+            self.m_tree.SetItemText(child, 1, ' ' + _type)
+            self.m_tree.SetItemData(child, (r[rpdb2.DICT_KEY_EXPR], r[rpdb2.DICT_KEY_IS_VALID]))
+            SetItemHasChildren(self.m_tree, child, (r[rpdb2.DICT_KEY_N_SUBNODES] > 0))
 
         self.m_tree.Expand(item)
 
     
     def OnItemExpanding(self, event):
         item = event.GetItem()        
+        print('OnItemExpanding(item=%s)' % ItemToStr(item))
 
-        if not self.m_tree.ItemHasChildren(item):
+        if not ItemHasChildren(self.m_tree, item):
             event.Skip()
             return
         
         if self.GetChildrenCount(item) > 0:
             event.Skip()
-            self.m_tree.Refresh();
+            self.m_tree.Refresh()
             return
             
+        print('OnItemExpanding() - repopulathing children')
         self.m_tree.DeleteChildren(item)
         
         child = self.m_tree.AppendItem(item, STR_NAMESPACE_LOADING)
-        self.m_tree.SetItemText(child, ' ' + STR_NAMESPACE_LOADING, 2)
-        self.m_tree.SetItemText(child, ' ' + STR_NAMESPACE_LOADING, 1)
-        self.m_tree.SetItemPyData(child, (STR_NAMESPACE_LOADING, False))
+        self.m_tree.SetItemText(child, 2, ' ' + STR_NAMESPACE_LOADING)
+        self.m_tree.SetItemText(child, 1, ' ' + STR_NAMESPACE_LOADING)
+        self.m_tree.SetItemData(child, (STR_NAMESPACE_LOADING, False))
 
-        (expr, is_valid) = self.m_tree.GetPyData(item)
+        (expr, is_valid) = self.m_tree.GetItemData(item)
 
         f = lambda r, exc_info: self.callback_ns(r, exc_info, expr)        
         self.m_async_sm.with_callback(f).get_namespace([(expr, True)], self.m_filter_level)
@@ -3586,9 +3662,9 @@ class CNamespacePanel(wx.Panel, CJobs):
     
         if t != None or r is None or len(r) == 0:
             child = self.m_tree.AppendItem(item, STR_NAMESPACE_DEADLOCK)
-            self.m_tree.SetItemText(child, ' ' + STR_NAMESPACE_DEADLOCK, 2)
-            self.m_tree.SetItemText(child, ' ' + STR_NAMESPACE_DEADLOCK, 1)
-            self.m_tree.SetItemPyData(child, (STR_NAMESPACE_DEADLOCK, False))
+            self.m_tree.SetItemText(child, 2, ' ' + STR_NAMESPACE_DEADLOCK)
+            self.m_tree.SetItemText(child, 1, ' ' + STR_NAMESPACE_DEADLOCK)
+            self.m_tree.SetItemData(child, (STR_NAMESPACE_DEADLOCK, False))
             self.m_tree.Expand(item)
 
             if freselect_child:
@@ -3608,7 +3684,7 @@ class CNamespacePanel(wx.Panel, CJobs):
     def find_item(self, expr):
         item = self.m_tree.GetRootItem()
         while item:
-            (expr2, is_valid) = self.m_tree.GetPyData(item)
+            (expr2, is_valid) = self.m_tree.GetItemData(item)
             if expr2 == expr:
                 return item               
                 
@@ -3618,18 +3694,20 @@ class CNamespacePanel(wx.Panel, CJobs):
     
 
     def get_children(self, item):
-        (child, cookie) = self.m_tree.GetFirstChild(item)
+        print('get_children(%s)' % (ItemToStr(self.m_tree, item)))
+        (child, cookie) = self.m_tree.GetFirstChild(item), 'cookie'
         cl = []
         
         while child and child.IsOk():
             cl.append(child)
-            (child, cookie) = self.m_tree.GetNextChild(item, cookie)
+            child = self.m_tree.GetNextSibling(item)
 
         return cl    
 
                              
     def get_expression_list(self):
-        if self.m_tree.GetCount() == 0:
+        print('get_expession_list()')
+        if self.m_tree.GetFirstItem().IsOk() == False:
             return None
 
         item = self.m_tree.GetRootItem()
@@ -3639,7 +3717,7 @@ class CNamespacePanel(wx.Panel, CJobs):
 
         while len(s) > 0:
             item = s.pop(0)
-            (expr, is_valid) = self.m_tree.GetPyData(item)
+            (expr, is_valid) = self.m_tree.GetItemData(item)
             fExpand = self.m_tree.IsExpanded(item) and self.GetChildrenCount(item) > 0
             if not fExpand:
                 continue
@@ -3648,10 +3726,19 @@ class CNamespacePanel(wx.Panel, CJobs):
             items = self.get_children(item)
             s = items + s
 
+        print('get_expession_list() -> el=%s, s=%s' % (el, s))
         return el    
 
 
     def update_namespace(self, key, el):
+        '''Arguments:
+        - key: unique value identifying a namespace
+        - el: namespace content
+
+        Returns:
+        - (previous key, previous element)
+        '''
+        print('update_namespace(key=%s, el=%s)' % (key, el))        
         old_key = self.m_key
         old_el = self.get_expression_list()
 
@@ -3660,7 +3747,7 @@ class CNamespacePanel(wx.Panel, CJobs):
 
         self.m_key = key
 
-        if el is None:
+        if not el:
             el = [(self.get_root_expr(), True)]
 
         self.post(el, self.m_filter_level)
@@ -3699,21 +3786,28 @@ class CNamespacePanel(wx.Panel, CJobs):
 
         
     def do_update_namespace(self, rl):    
+        '''Arguments:
+        rl: list of dictionnaries, each element of the list describes a python expression
+
+        See CSessionManager.get_namespace() for more details'''
+        print('do_update_namespace(rl=%s)' % pprint.pformat(rl, 4) )
         self.m_tree.DeleteAllItems()
 
-        root = self.m_tree.AddRoot('root')
-        self.m_tree.SetItemPyData(root, (self.get_root_expr(), False))
-        self.m_tree.SetItemHasChildren(root, True)
+        # root = self.m_tree.AddRoot('root')
+        root = self.m_tree.GetRootItem()
+        self.m_tree.SetItemData(root, (self.get_root_expr(), False))
+        SetItemHasChildren(self.m_tree, root, True)
 
         s = [root]
 
         while len(s) > 0:
             item = s.pop(0)
+            print('do_update_namespace() - populating item %s' % ItemToStr(self.m_tree, item))
             self.expand_item(item, rl, item is root)
             
             items = self.get_children(item)
             s = items + s
-
+        print('s="%s"' % s)
         self.m_tree.Refresh()
 
 
@@ -3805,6 +3899,9 @@ class CNamespaceViewer(wx.Panel, CCaptio
 
 
     def get_local_key(self, _stack):
+        '''Arguments:
+        _stack: a dictionnary describing the current thread. See rpdb2.py:get_stack() for detailed information.
+        '''
         frame_index = self.m_session_manager.get_frame_index()
         c = _stack.get(rpdb2.DICT_KEY_CODE_LIST, [])
         key = c[-(1 + frame_index)]
@@ -3812,6 +3909,9 @@ class CNamespaceViewer(wx.Panel, CCaptio
 
             
     def get_global_key(self, _stack):
+        '''Arguments:
+        _stack: a dictionnary describing the current thread. See rpdb2.py:get_stack() for detailed information.
+        '''
         frame_index = self.m_session_manager.get_frame_index()
         s = _stack.get(rpdb2.DICT_KEY_STACK, [])
         key = s[-(1 + frame_index)][0]
@@ -3819,6 +3919,9 @@ class CNamespaceViewer(wx.Panel, CCaptio
 
             
     def update_namespace(self, _stack):
+        '''Arguments:
+        _stack: a dictionnary describing the current thread. See rpdb2.py:get_stack() for detailed information.
+        '''
         try:
             key = self.get_local_key(_stack)
             el = self.m_key_map.get(key, None)
@@ -3873,7 +3976,7 @@ class CStackViewer(wx.Panel, CCaptionMan
 
 
     def set_cursor(self, id):
-        cursor = wx.StockCursor(id)
+        cursor = wx.Cursor(id)
         self.SetCursor(cursor)        
         self.m_stack.SetCursor(cursor)        
 
@@ -3908,14 +4011,14 @@ class CStackViewer(wx.Panel, CCaptionMan
             function = e[2]
 
             if not g_fUnicode:
-                filename = rpdb2.as_string(filename, wx.GetDefaultPyEncoding())
-                function = rpdb2.as_string(function, wx.GetDefaultPyEncoding())
+                filename = rpdb2.as_string(filename)
+                function = rpdb2.as_string(function)
 
-            index = self.m_stack.InsertStringItem(sys.maxint, repr(i))
-            self.m_stack.SetStringItem(index, 1, os.path.basename(filename))
-            self.m_stack.SetStringItem(index, 2, repr(lineno))
-            self.m_stack.SetStringItem(index, 3, function)
-            self.m_stack.SetStringItem(index, 4, os.path.dirname(filename))
+            index = self.m_stack.InsertItem( i, repr(i))
+            self.m_stack.SetItem(index, 1, os.path.basename(filename))
+            self.m_stack.SetItem(index, 2, repr(lineno))
+            self.m_stack.SetItem(index, 3, function)
+            self.m_stack.SetItem(index, 4, os.path.dirname(filename))
             self.m_stack.SetItemData(index, i)
 
             i += 1
@@ -4116,7 +4219,7 @@ class CAttachDialog(wx.Dialog, CJobs):
 
                 
     def set_cursor(self, id):
-        cursor = wx.StockCursor(id)
+        cursor = wx.Cursor(id)
         self.SetCursor(cursor)        
         self.m_listbox_scripts.SetCursor(cursor)        
 
@@ -4135,7 +4238,7 @@ class CAttachDialog(wx.Dialog, CJobs):
         if host == '':
             host = 'localhost'
 
-        host = rpdb2.as_unicode(host, wx.GetDefaultPyEncoding())
+        host = rpdb2.as_unicode(host)
 
         f = lambda r, exc_info: self.callback_sethost(r, exc_info, host)
         self.m_async_sm.with_callback(f).set_host(host)
@@ -4197,13 +4300,13 @@ class CAttachDialog(wx.Dialog, CJobs):
         self.m_listbox_scripts.DeleteAllItems()
 
         for i, s in enumerate(self.m_server_list):
-            index = self.m_listbox_scripts.InsertStringItem(sys.maxint, repr(s.m_pid))
+            index = self.m_listbox_scripts.InsertItem( i, repr(s.m_pid))
             
             filename = s.m_filename
             if not g_fUnicode:
-                filename = rpdb2.as_string(filename, wx.GetDefaultPyEncoding())
+                filename = rpdb2.as_string(filename)
 
-            self.m_listbox_scripts.SetStringItem(index, 1, filename)
+            self.m_listbox_scripts.SetItem(index, 1, filename)
             self.m_listbox_scripts.SetItemData(index, i)
 
         self.m_listbox_scripts.set_columns_width()
@@ -4216,7 +4319,7 @@ class CAttachDialog(wx.Dialog, CJobs):
         
 
     def OnItemSelected(self, event):
-        self.m_index = event.m_itemIndex
+        self.m_index = event.Index
         self.m_ok.Enable()
 
         event.Skip()
@@ -4230,7 +4333,7 @@ class CAttachDialog(wx.Dialog, CJobs):
 
         
     def OnItemActivated(self, event):
-        self.m_index = event.m_itemIndex
+        self.m_index = event.Index
 
         self.EndModal(wx.ID_OK)
         
@@ -4252,7 +4355,7 @@ class CExpressionDialog(wx.Dialog):
         sizerh.Add(label, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
 
         if not g_fUnicode:
-            default_value = rpdb2.as_string(default_value, wx.GetDefaultPyEncoding())
+            default_value = rpdb2.as_string(default_value)
 
         self.m_entry_expr = wx.TextCtrl(self, value = default_value, size = (200, -1))
         self.m_entry_expr.SetFocus()
@@ -4286,7 +4389,7 @@ class CExpressionDialog(wx.Dialog):
                    
     def get_expression(self):
         expr = self.m_entry_expr.GetValue()
-        expr = rpdb2.as_unicode(expr, wx.GetDefaultPyEncoding())
+        expr = rpdb2.as_unicode(expr)
 
         return expr
 
@@ -4313,7 +4416,7 @@ class CEncodingDialog(wx.Dialog):
         sizerh.Add(label, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
         encoding = [current_encoding, ''][current_encoding is None]
         if not g_fUnicode:
-            encoding = rpdb2.as_string(encoding, wx.GetDefaultPyEncoding())
+            encoding = rpdb2.as_string(encoding)
 
         self.m_entry_encoding = wx.TextCtrl(self, value = encoding, size = (200, -1))
         self.m_entry_encoding.SetFocus()
@@ -4353,7 +4456,7 @@ class CEncodingDialog(wx.Dialog):
                    
     def get_encoding(self):
         encoding = self.m_entry_encoding.GetValue()
-        encoding = rpdb2.as_unicode(encoding, wx.GetDefaultPyEncoding())
+        encoding = rpdb2.as_unicode(encoding)
 
         return encoding, self.m_cb.GetValue()
 
@@ -4446,7 +4549,7 @@ class CPwdDialog(wx.Dialog):
         pwd = [current_password, ''][current_password is None]
 
         if not g_fUnicode:
-            pwd = rpdb2.as_string(pwd, wx.GetDefaultPyEncoding())
+            pwd = rpdb2.as_string(pwd)
 
         self.m_entry_pwd = wx.TextCtrl(self, value = pwd, size = (200, -1))
         self.m_entry_pwd.SetFocus()
@@ -4482,7 +4585,7 @@ class CPwdDialog(wx.Dialog):
                    
     def get_password(self):
         pwd = self.m_entry_pwd.GetValue()
-        pwd = rpdb2.as_unicode(pwd, wx.GetDefaultPyEncoding())
+        pwd = rpdb2.as_unicode(pwd)
 
         return pwd
 
@@ -4562,7 +4665,7 @@ class COpenDialog(wx.Dialog):
         (_path, filename, args) = rpdb2.split_command_line_path_filename_args(command_line)
         _abs_path = os.path.abspath(_path)
 
-        dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = WILDCARD_WINPDB, style = wx.OPEN | wx.CHANGE_DIR)
+        dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = WILDCARD_WINPDB, style = wx.FD_OPEN | wx.FD_CHANGE_DIR)
         r = dlg.ShowModal()
         if r == wx.ID_OK:
             path = dlg.GetPaths()[0]
@@ -4579,7 +4682,7 @@ class COpenDialog(wx.Dialog):
 
     def get_file_name(self):
         filename = self.m_entry.GetValue()
-        filename = rpdb2.as_unicode(filename, wx.GetDefaultPyEncoding())
+        filename = rpdb2.as_unicode(filename)
 
         return filename
 
@@ -4603,7 +4706,7 @@ class CLaunchDialog(wx.Dialog):
         sizerh.Add(label, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
 
         if not g_fUnicode:
-            command_line = rpdb2.as_string(command_line, wx.GetDefaultPyEncoding())
+            command_line = rpdb2.as_string(command_line)
 
         self.m_entry_commandline = wx.TextCtrl(self, value = command_line, size = (200, -1))
         self.m_entry_commandline.SetFocus()
@@ -4676,7 +4779,7 @@ class CLaunchDialog(wx.Dialog):
 
         cwd = rpdb2.getcwdu()
             
-        dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = WILDCARD_WINPDB, style = wx.OPEN | wx.CHANGE_DIR)
+        dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = WILDCARD_WINPDB, style = wx.FD_OPEN | wx.FD_CHANGE_DIR)
         r = dlg.ShowModal()
 
         os.chdir(cwd)
@@ -4705,7 +4808,7 @@ class CLaunchDialog(wx.Dialog):
         else:
             wildcard = WILDCARD_EXECUTABLES
             
-        dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = wildcard, style = wx.OPEN | wx.CHANGE_DIR)
+        dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = wildcard, style = wx.FD_OPEN | wx.FD_CHANGE_DIR)
         r = dlg.ShowModal()
 
         os.chdir(cwd)
@@ -4726,7 +4829,7 @@ class CLaunchDialog(wx.Dialog):
         
     def do_validate(self):
         command_line = self.m_entry_commandline.GetValue()
-        command_line = rpdb2.as_unicode(command_line, wx.GetDefaultPyEncoding())
+        command_line = rpdb2.as_unicode(command_line)
         
         (_path, filename, args)  = rpdb2.split_command_line_path_filename_args(command_line)
         
@@ -4769,7 +4872,7 @@ class CLaunchDialog(wx.Dialog):
         
     def get_command_line(self):
         command_line = self.m_entry_commandline.GetValue()
-        command_line = rpdb2.as_unicode(command_line, wx.GetDefaultPyEncoding())
+        command_line = rpdb2.as_unicode(command_line)
         interpreter = self.m_entry_interpreter.GetValue()
         return (command_line, self.m_cb.GetValue(), interpreter)
 
@@ -4789,7 +4892,7 @@ def StartClient(command_line, fAttach, f
         raise
         
     if not 'unicode' in wx.PlatformInfo:
-        dlg = wx.Mes8ageDialog(None, STR_WXPYTHON_ANSI_WARNING_MSG, STR_WXPYTHON_ANSI_WARNING_TITLE, wx.OK | wx.ICON_WARNING)
+        dlg = wx.MessageDialog(None, STR_WXPYTHON_ANSI_WARNING_MSG, STR_WXPYTHON_ANSI_WARNING_TITLE, wx.OK | wx.ICON_WARNING)
         dlg.ShowModal()
         dlg.Destroy()
     
@@ -4800,17 +4903,14 @@ def StartClient(command_line, fAttach, f
 
 
 def main():
-    if rpdb2.get_version() != "RPDB_1_5_0":
-        rpdb2._print(STR_ERROR_INTERFACE_COMPATIBILITY % ("0PDB_1_5_0", rpdb2.get_version()))
+    if rpdb2.get_version() != RPDB2_EXPECTED_VERSION:
+        rpdb2._print(STR_ERROR_INTERFACE_COMPATIBILITY % ( RPDB2_EXPECTED_VERSION, rpdb2.get_version()))
         return
         
     return rpdb2.main(StartClient, WINPDB_TITLE)
 
 
 
-def get_version():
-    return WINPDB_VERSION
-
 def run_winpdb():
     ret = main()