This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author veky
Recipients serhiy.storchaka, terry.reedy, veky
Date 2016-08-24.21:21:19
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1472073680.87.0.329912986962.issue27821@psf.upfronthosting.co.za>
In-reply-to
Content
Well, I don't know how good this comment box is for a pdb tutorial. :-) And I learned it a long time ago, so I don't really remember how it is to not know it. :-/ The main reason I love it is purely sentimental: it reminds me of those silly text-based adventure games. If you played Zork, you'll feel right at home. :-D

(If you want a more "ordinary" introduction, yet refreshingly different than the boring stdlib manpage, visit https://pythonconquerstheuniverse.wordpress.com/2009/09/10/debugging-in-python/.)

You put "import pdb; pdb.set_trace()" (or "__import__('pdb').set_trace()" if you hate semicolons more than dunders:) before the line you want to set a breakpoint in. Then you run the program normally. When it hits a breakpoint, it gives you a (Pdb) prompt, and you can look around.

(Alternatively, when you get an exception, just "import pdb; pdb.pm()" for a post-mortem debugger. All the stack frames that lead to exception are preserved with all their local variables, nicely inspectable. Beautiful.:)

`u` and `d` (up and down) are the elevator buttons that move you along the frame stack: u towards earlier (outer) calls, d towards later (inner) calls. `w` (where) lets you see which "floor" you're on.

On every floor, `p` (print) and `pp` (prettyprint) give you information about various objects you see, like "examine" in text adventures :-). `!` lets you execute an arbitrary Python statement (! is not needed in most cases, but it's good to make a habit of writing it) _inside the current stackframe_ (yes, everything is live:). `interact` gives you a full Python shell attached on the current frame.

`l` lists a few lines around your current place, `ll` lists the whole function (or another meaningful whole). `a` gives you the arguments for the current function call.

`s` and `r` are the "in" and "out" commands, allowing you to step inside and return from currently called function. `n` is just "next", meaning "execute current line and show me the next one". Unfortunately, `n` has no inverse (you cannot undo an executed statement), but `j` is a (limited) goto. If you go too far into a strange land, `run` restarts the program from the beginning.

pdb always shows the line it's about to execute (it's not yet executed). Just pressing Enter repeats the last given command (in case of `l`, keeps listing onwards).

`c` means quit the debugger and continue executing program normally. `q` means quit the debugger and program altogether. There are many more commands, but those are kinda basic ones to know your way around.

Ok, now what I've done with IDLE. You mentioned configdialog.py, line 1066. I go there and find a function

    def LoadKeyCfg(self):

Ok, that's obviously the function I have to trace. As the first statement in that function, I put "import pdb; pdb.set_trace()" call and save the file. Then I go to command prompt, and start IDLE. I go to Options > Configure IDLE, and sure enough, at my command prompt there is

> c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\configdialog.py(1069)LoadKeyCfg()
-> self.keysAreBuiltin.set(idleConf.GetOption(
(Pdb)

a Pdb prompt. I type l and Enter, to see where I am in the code.

(Pdb) l
1064            self.SetHighlightTarget()
1065
1066        def LoadKeyCfg(self):
1067            import pdb; pdb.set_trace()
1068            ##current keys type radiobutton
1069 ->         self.keysAreBuiltin.set(idleConf.GetOption(
1070                    'main', 'Keys', 'default', type='bool', default=1))
1071            ##currently set keys
1072            currentOption = idleConf.CurrentKeys()
1073            ##load available keyset option menus
1074            if self.keysAreBuiltin.get(): #default theme selected
(Pdb)

Ok, so it's going to set a Tkinter variable (I know by seeing ".set", but there is also a `whatis` command if you want to see the type of something). I say n to execute it (twice because it's two lines), and then

(Pdb) p self.keysAreBuiltin.get()
False
(Pdb)

So far so good. Keys aren't builtin.

(Pdb) n
> c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\configdialog.py(1072)LoadKeyCfg()
-> currentOption = idleConf.CurrentKeys()

Ok, now it's going to set CurrentKeys.

(Pdb) n
...
(Pdb) p idleConf.CurrentKeys()
'IDLE Classic Windows'

Ok, this shouldn't happen. Let's goto it again (hoping there aren't many sideeffects:) and step into it this time.

(Pdb) l
1069            self.keysAreBuiltin.set(idleConf.GetOption(
1070                    'main', 'Keys', 'default', type='bool', default=1))
1071            ##currently set keys
1072            currentOption = idleConf.CurrentKeys()
1073            ##load available keyset option menus
1074 ->         if self.keysAreBuiltin.get(): #default theme selected
1075                itemList = idleConf.GetSectionList('default', 'keys')
1076                itemList.sort()
1077                self.optMenuKeysBuiltin.SetMenu(itemList, currentOption)
1078                itemList = idleConf.GetSectionList('user', 'keys')
1079                itemList.sort()
(Pdb)

So it's line 1072.

(Pdb) j 1072
> c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\configdialog.py(1072)LoadKeyCfg()
-> currentOption = idleConf.CurrentKeys()
(Pdb) s
--Call--
> c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\config.py(368)CurrentKeys()
-> def CurrentKeys(self):
(Pdb) l
363
364         def CurrentTheme(self):
365             "Return the name of the currently active text color theme."
366             return self.current_colors_and_keys('Theme')
367
368  ->     def CurrentKeys(self):
369             """Return the name of the currently active key set."""
370             return self.current_colors_and_keys('Keys')
371
372         def current_colors_and_keys(self, section):
373             """Return the currently active name for Theme or Keys section.
(Pdb) n
> c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\config.py(370)CurrentKeys()
-> return self.current_colors_and_keys('Keys')
(Pdb) s
--Call--
> c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\config.py(372)current_colors_and_keys()
-> def current_colors_and_keys(self, section):
(Pdb) 

A few `n`s, and we have a culprit. `ll` to see a whole function and confirm our suspicion, and a final test: make a new color theme. It works. Victory! :-)
History
Date User Action Args
2016-08-24 21:21:21vekysetrecipients: + veky, terry.reedy, serhiy.storchaka
2016-08-24 21:21:20vekysetmessageid: <1472073680.87.0.329912986962.issue27821@psf.upfronthosting.co.za>
2016-08-24 21:21:20vekylinkissue27821 messages
2016-08-24 21:21:19vekycreate