How could I possibly find a bug that I can not reproduce? I thought... Thus began an exchange of emails that led me to find a way to reproduce the bug and, eventually, to solve it. The final solution was somewhat typical of my experience with Python: try the obvious!
These last three words are probably the best words of advice I could give to anyone who writes computer programs using Python. If you are reading this blog as a potential source of useful tips [you fool!], you should probably stop now as nothing else I will write is likely to come even close to being as useful to you.
However, if you want to get a good laugh at my expense, you are invited to continue reading.
I first started by asking M.H. what everyone always asks me when I claim to find a bug or when I don't understand the behaviour of some module and post some question on various lists.
What OS and what version of wxPython are you using?
I expected that M.H. was using Mac OS or Linux, in which case I was getting ready to diplomatically tell him that he was likely out of luck as I'm [shame on me], a Windows user. However, M.H. told me that he was using Win XP (same here), Python 2.4.3 (I'm using 2.4.2) and wxPython 2.6 (same here).
Ok. I was more stumped then ever. This was bugging me... These days, I'm working on Crunchy Frog which will, eventually, include and supersede RUR-PLE. As it is, I have a lot more ideas than time at my disposal to work on Crunchy Frog, and this "distraction" was not welcome. However, I could not ignore it.
Since I couldn't reproduce the bug, I asked M.H. if he could do me a favour and insert a print statement in the method where the line number was set for the purpose of highlighting. As I wrote the email, I had a "clever" thought. M.H. is in the U.S. He's probably using the ansi version of wxPython whereas I'm using the unicode version. I bet you something's wrong with that version... Sure enough, my first hunch was right: M.H. was using the ansi version. And the print statement was outputting the same result on his computer as it was on mine. So, if one hunch was right... I asked M.H. to install the wxPython unicode version, which he kindly agreed to.
Same result... Of course, you are no doubt thinking. However, you are not trying to quash a bug you can't even reproduce. [That's my excuse, anyway.]
At that time I was visiting my partner who, unfortunately, lives 300 km (200 mi) from where I live. Fortunately, she is extremely patient and puts up with me when I am distracted by a programming problem. I decided to install wxPython and the latest version of RUR-PLE on her computer to investigate some more.
Ooops... wxPython is now at version 184.108.40.206. I am sure the version installed on my computer is 220.127.116.11. I read over the "changes" document to see if I can find anything that I can use. There does not appear to be anything relevant. I install the new version ... sure enough, I can "see" the bug (or, should I say, I can't see anything as no highlighting is taking place).
I read the "changes" document a second (and third) time, just to be sure. No luck.
Time to dig in my code. [... Where is this object initialised?... This could have been written so much better... What was I thinking then (about a year ago)... ] After staring at the code for a while, being convinced that the highlighting information is properly set (it was working before, after all) I am convinced it is a wxPython bug that was introduced. I file a bug report and expect to leave it at that.
However, my conscience is nagging me. I decide to look at the code again, staring at the method where the highlighting updates should take place. Here it is, with a few added notes.
def update_refresh(self, robot, name):
if 'robot' in self.robot_dict: # (1)
arg = self.parent.status_bar.beeper_field, self.robot_dict['robot']._beeper_bag
time.sleep(robot.delay) # (2)
wx.Yield() # (3)
self.WorldDisplay.scrollWorld(name) # (6)
self.WorldDisplay.Refresh() # (7)
- The information in the status bar (number of beepers carried by robot, etc.) is updated.
- The animation is paused at each step.
- Making sure other controls of the application are responsive so that the program can be paused or stopped altogether by pressing the appropriate button, etc.
- Update the (in-memory) image based on the latest robot action.
- Update the screen image.
- Prevent the robot from going off the screen.
- Refresh the screen [Refresh() is a wxPython method.]
Can you see the bug?
I didn't refresh the code window. It worked before though.
How do I do this... the robot world is a ScrolledWindow whereas the code window is a StyledTextControl... Where do I find the relevant documentation...
That's when I thought of the three important words I mentioned before: try the obvious. I typed in
and launched RUR-PLE. Problem solved. I guess it was just dumb luck that this refresh statement was not required before. All I have to do now is fix the bug and update the version on sourceforge ... before I go back and rewrite the parts of the code that I didn't find easy to read just a few days ago.