Home ........ Blog ........ Travels ........ Software ........ Web 3D ........ LinkedIn

Friday, August 21, 2015

Notepad++, DBGP and ... Python!

My recent work with Notepad++ got Perl debugging working with the DBGP Plugin. Originally written for PHP debugging, I did a little tweaking on the Perl side and got it working.

I don't know a lick of Python, but could I get Python to work with the DBGP Plugin too? Worth a shot!

First step was to get a Python debugging engine. For that, I relied on the same site as I got the Perl debugger - Komodo IDE. I grabbed the Python for Win32 flavor this time and extracted the ZIP contents (specifically all the files and subdirectories in the "Komodo-PythonRemoteDebugging-4.4.1-20896-win32-x86" directory) to a newly created directory called 'PythonDebug' in my Notepad++ plugins folder. So far, same procedure as getting Perl to work.

From here I dove right into NppExec automation. For Python, you'll need:

NPP_SAVE
cd "$(CURRENT_DIRECTORY)"
NPP_MENUCOMMAND Plugins\DBGp\Debugger
INPUTBOX "Command Line Arguments: "
ENV_SET PYTHONPATH=$(SYS.PYTHONPATH);$(NPP_DIRECTORY)\plugins\PythonDebug\dbgp
cmd /c python.exe -S $(NPP_DIRECTORY)\plugins\PythonDebug\bin\pydbgp.py -d 127.0.0.1:9000 "$(FILE_NAME)" $(INPUT)

A quick test showed it worked, but failed miserably - much like with Perl. I'd need to do some debugger debugging!

The "RAW" button on the DBGP Plugin is instrumental in this quest. It's basically a DBGp protocol decoder displaying messages sent and received between the Notepad++ plugin and the debugging engine. In the Python case, the most obvious deviation from the DBGP specification was the use of extended_properties without actually negotiating them.

I found that in the toxml() definition in the Property: class of the 'dbgp/client.py' file. With my very limited Python skills, I was still able to hack it to work! The changes are a bit long to post here, but they involved removing the extra XML tags, assigning the name / value pairs appended to childprops[] to the attrs[] array instead and moving the attrs[] array definition to earlier in the code.

The next issue involved setting breakpoints. After setting a breakpoint, I'd get an error from the debugger about not being able to map the remote file and it was clearly showing an 'idekey' set to my username. I hadn't set an IDEKEY on purpose so a quick search turned up some scattered 'if' statements:

  if not idekey:
      idekey = getenv('USER', getenv('USERNAME',''))

We don't want that. So a simple fix (3 places in 'dbgp/client.py' and one in 'bin/pydbgp.py'):

  if not idekey:
      idekey = '' # getenv('USER', getenv('USERNAME',''))

Thanks Python, but if I don't set an IDEKEY, I really don't want or need one.

But breakpoints still were failing. Upon closer examination with the DBGP Plugin's 'RAW' button and a successful run with the Perl debugger, I noticed the value passed back for the 'filename' attribute from the Python debugger was wrong. It was simply passing back the file name (e.g., "C:\temp\pythonscript.py") instead of a URL path (e.g., "file:///C:/temp/pythonscript.py"). It was an easy find; in the toxml() definition in the Breakpoint: class of the 'dbgp/client.py' file:

    bp += ' filename="%s" lineno="%s"' % (self.file, self.line)

The weird part was other Python debugger results had the URL string instead of the file name path. I looked for a conversion routine in the Python debugger and found it: pathname2url(). An easy fix; the line above became:

    bp += ' filename="%s" lineno="%s"' % (pathname2url(self.file), self.line)

Finally, a full fledged test worked ... for the most part. As with Perl, there are a few hiccups, but I get variable watches and expansion for child lists, breakpoint and step through ability. Everything I'll ever need for debugging the Python scripts I'll never write!

Anyway, it was a good learning experience and another coup for Notepad++ and the awesome DBGP Plugin!

No comments :

 

Copyright © VinsWorld. All Rights Reserved.