From ccba0fa44081fafa0b27303d423de3b042f74391 Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Aug 15 2019 17:54:16 +0000 Subject: update to 2.0.0dev5, python3 --- diff --git a/.gitignore b/.gitignore index be1e212..0499392 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ winpdb-1.4.6.tar.gz /winpdb-1.4.8.tar.gz +/WINPDB_1_5_0.tar.gz diff --git a/sources b/sources index d2efd48..b9ec0ef 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -e28049cc93c1614b9db20960d76b7ea3 winpdb-1.4.8.tar.gz +SHA512 (WINPDB_1_5_0.tar.gz) = 9d4104e93c512dab3f1cd52b861b021b341cd0aaf5d65d1235cef546ce6e6dcedcb699a50f40f5c582d4dc1789dc66ae70c2c1cab9d4ff3afcd1d796e055b8db diff --git a/winpdb-1.4.8-gnome-fix.patch b/winpdb-1.4.8-gnome-fix.patch deleted file mode 100644 index 8a64c13..0000000 --- a/winpdb-1.4.8-gnome-fix.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up winpdb-1.4.8/rpdb2.py.gnomefix winpdb-1.4.8/rpdb2.py ---- winpdb-1.4.8/rpdb2.py.gnomefix 2014-12-04 15:19:38.972288993 -0500 -+++ winpdb-1.4.8/rpdb2.py 2014-12-04 15:19:47.279229223 -0500 -@@ -1780,7 +1780,7 @@ osSpawn = { - NT_DEBUG: 'start "rpdb2 - Version ' + get_version() + ' - Debuggee Console" cmd.exe /K ""%(exec)s" %(options)s"', - POSIX: "%(term)s -e %(shell)s -c '%(exec)s %(options)s; %(shell)s' &", - 'Terminal': "Terminal --disable-server -x %(shell)s -c '%(exec)s %(options)s; %(shell)s' &", -- GNOME_DEFAULT_TERM: "gnome-terminal --disable-factory -x %(shell)s -c '%(exec)s %(options)s; %(shell)s' &", -+ GNOME_DEFAULT_TERM: "gnome-terminal -x %(shell)s -c '%(exec)s %(options)s; %(shell)s' &", - MAC: '%(exec)s %(options)s', - DARWIN: '%(exec)s %(options)s', - SCREEN: 'screen -t debuggee_console %(exec)s %(options)s' diff --git a/winpdb-1.4.8-issue19-fix.patch b/winpdb-1.4.8-issue19-fix.patch deleted file mode 100644 index 794c0af..0000000 --- a/winpdb-1.4.8-issue19-fix.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up winpdb-1.4.8/rpdb2.py.issue19 winpdb-1.4.8/rpdb2.py ---- winpdb-1.4.8/rpdb2.py.issue19 2015-04-01 08:47:34.601072072 -0400 -+++ winpdb-1.4.8/rpdb2.py 2015-04-01 08:48:02.336901383 -0400 -@@ -12056,7 +12056,7 @@ class CConsoleInternal(cmd.Cmd, threadin - - - def __parse_bp_arg(self, arg, fAllowExpr = True): -- _args = arg.split(BP_EVAL_SEP) -+ _args = arg.split(BP_EVAL_SEP, 1) - - if (len(_args) > 1) and (not fAllowExpr): - raise BadArgument diff --git a/winpdb-2.0.0dev5.patch b/winpdb-2.0.0dev5.patch new file mode 100644 index 0000000..825d683 --- /dev/null +++ b/winpdb-2.0.0dev5.patch @@ -0,0 +1,1338 @@ +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 = "" + ML_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() + diff --git a/winpdb.spec b/winpdb.spec index 3340b96..fba560f 100644 --- a/winpdb.spec +++ b/winpdb.spec @@ -1,19 +1,18 @@ Name: winpdb -Version: 1.4.8 -Release: 21%{?dist} +Version: 2.0.0 +Release: 0.1.dev5%{?dist} Summary: An advanced python debugger License: GPLv2+ -URL: http://www.winpdb.org/ -Source0: http://winpdb.googlecode.com/files/winpdb-%{version}.tar.gz +URL: https://pypi.org/project/winpdb-reborn +Source0: https://github.com/bluebird75/winpdb/archive/WINPDB_1_5_0.tar.gz Source1: %{name}.desktop Source2: %{name}.png -Patch0: winpdb-1.4.8-gnome-fix.patch -Patch1: https://sources.debian.net/data/main/w/winpdb/1.4.8-2.1/debian/patches/wxpython3.0.patch -# https://code.google.com/p/winpdb/issues/detail?id=19 -Patch2: winpdb-1.4.8-issue19-fix.patch +# Brings us to current git as of 20190815 +Patch0: winpdb-2.0.0dev5.patch BuildArch: noarch -BuildRequires: python2-devel, wxPython-devel >= 2.6, desktop-file-utils -Requires: python2-crypto, python2-wxpython >= 2.6 +BuildRequires: python3-devel, wxPython-devel >= 2.6, desktop-file-utils +Requires: python3-crypto, python3-wxpython4 +Provides: winpdb-reborn = %{version}-%{release} %description Winpdb is an advanced python debugger, with support for smart breakpoints, @@ -21,21 +20,16 @@ multiple threads, namespace modification, embedded debugging, encrypted communication and speed of up to 20 times that of pdb. %prep -%setup -q -%patch0 -p1 -b .gnomefix -%patch1 -p1 -b .wxpy3 -%patch2 -p1 -b .issue19 -sed -i 's/\r//g' README.txt -chmod -x README.txt - -sed -i 's|/usr/bin/env python|/usr/bin/python2|g' rpdb2.py -sed -i 's|/usr/bin/env python|/usr/bin/python2|g' winpdb.py +%setup -q -n %{name}-WINPDB_1_5_0 +%patch0 -p1 -b .dev5 +sed -i 's|/usr/bin/env python|/usr/bin/python3|g' rpdb2.py +sed -i 's|/usr/bin/env python|/usr/bin/python3|g' winpdb.py %build -%{__python2} setup.py build +%{__python3} setup.py build %install -%{__python2} setup.py install --skip-build --root=$RPM_BUILD_ROOT +%{__python3} setup.py install --skip-build --root=$RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{_datadir}/pixmaps install -m0644 -p %{SOURCE2} $RPM_BUILD_ROOT%{_datadir}/pixmaps @@ -45,16 +39,19 @@ desktop-file-install \ --dir $RPM_BUILD_ROOT%{_datadir}/applications \ %{SOURCE1} -chmod +x $RPM_BUILD_ROOT%{python2_sitelib}/rpdb2.py $RPM_BUILD_ROOT%{python2_sitelib}/winpdb.py +chmod +x $RPM_BUILD_ROOT%{python3_sitelib}/rpdb2.py $RPM_BUILD_ROOT%{python3_sitelib}/winpdb.py %files -%doc README.txt +%doc README.rst %{_bindir}/* -%{python2_sitelib}/* +%{python3_sitelib}/* %{_datadir}/applications/*.desktop %{_datadir}/pixmaps/%{name}.png %changelog +* Thu Aug 15 2019 Tom Callaway - 2.0.0-0.1.dev5 +- use winpdb-reborn sources, move to python3 + * Sat Jul 27 2019 Fedora Release Engineering - 1.4.8-21 - Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild diff --git a/wxpython3.0.patch b/wxpython3.0.patch deleted file mode 100644 index a60e525..0000000 --- a/wxpython3.0.patch +++ /dev/null @@ -1,47 +0,0 @@ -Description: Fixes for wxPython 3.0 - Retains compatibility with 2.8. -Author: Olly Betts -Bug-Debian: https://bugs.debian.org/759093 -Forwarded: no -Last-Update: 2014-09-20 - -Index: winpdb-1.4.8/winpdb.py -=================================================================== ---- winpdb-1.4.8.orig/winpdb.py -+++ winpdb-1.4.8/winpdb.py -@@ -278,7 +278,7 @@ import sys - - - --WXVER = "2.6" -+WXVER = "2.8" - - STR_WXPYTHON_ERROR_TITLE = 'Winpdb Error' - STR_WXPYTHON_ERROR_MSG = """wxPython was not found. -@@ -3870,7 +3870,7 @@ class CHTMLDialog(wx.Dialog): - self.m_html.SetPage(self.get_html_text(text)) - - ir = self.m_html.GetInternalRepresentation() -- self.m_html.SetSize((ir.GetWidth() + 25, min(500, ir.GetHeight() + 25))) -+ self.m_html.SetMinSize((ir.GetWidth() + 25, min(500, ir.GetHeight() + 25))) - - btnsizer = wx.StdDialogButtonSizer() - sizerv.Add(btnsizer, 0, wx.ALIGN_CENTRE | wx.ALL, 5) -@@ -4465,7 +4465,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 = WINPDB_WILDCARD, style = wx.OPEN | wx.CHANGE_DIR) -+ dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = WINPDB_WILDCARD, style = wx.FD_OPEN | wx.FD_CHANGE_DIR) - r = dlg.ShowModal() - if r == wx.ID_OK: - path = dlg.GetPaths()[0] -@@ -4563,7 +4563,7 @@ class CLaunchDialog(wx.Dialog): - - cwd = rpdb2.getcwdu() - -- dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = WINPDB_WILDCARD, style = wx.OPEN | wx.CHANGE_DIR) -+ dlg = wx.FileDialog(self, defaultDir = _abs_path, defaultFile = filename, wildcard = WINPDB_WILDCARD, style = wx.FD_OPEN | wx.FD_CHANGE_DIR) - r = dlg.ShowModal() - - os.chdir(cwd)