My XBox Live Gamer Card
Friday, October 17. 2008
I have made some minor changes to RadioChoice.py, my widget that allows the creation of wx.Choice objects that function in groups like wx.RadioButtons.
It has been somewhat PEP 08'ified. Though the CamelCase of wxPython seems to always result in a few compromises. In general I try to make "public" methods CamelCase and "private" methods match PEP-08. As you can see I'm also torn on the subject of module names. I initially renamed the module "radiochoice", but from an aesthetic standpoint I hated the way it looked. You may eventually see the module name change though.
Monday, September 22. 2008
As I have been working to divorce my GUI from my model while building Rollem, I came upon a situation where I couldn't fully instantiate my RadioChoice widgets, and had to update the list of available choices after creating the widgets.
In it's original incarnation that was an impossible task. So I added a ResetItems() method which takes a new list of choices and replaces the original list. It can be called on any widget in the group and will replace the choice list across all widgets in the group. The new choice list must follow all the rules of the original choice list (i.e., have a "NULL" choice at the beginning of the list).
Here is some sample code showing how it all works:
After seeing how Wizards of the Coast handle the problem I was solving for in their online app, I am more convinced than ever that I took the correct route.
Wednesday, September 17. 2008
I've been working on Rollem my D&D character generator for a while. When I write I have to prevent myself from editing because once I start editing, I never finish writing and I'd dearly love to finish something someday. When I write code, I have discovered I have the same problem I re-factor, and re-factor and re-factor and never finish the project.
One of the problems with re-factoring is how do you know if the re-factor is correct?
My current refactor is completely and utterly divorcing the Model from the GUI code. They only interact via messages passed with PubSub. It's been tough as I try and re-mold my though processes to fit what is a new paradigm for me. This has entailed some significant code changes and many things are broken right this instant. They are broken to the point where I am sometimes despairing of ever making them work right. However, I do have one thing working in my favour. I have unit tests for my code. Those unit tests provide a wonderful to-do list for me in digging out of the hole I have created. They prevent me from throwing in the towel and starting over from scratch. They tell me when my re-factors work so I can move on to the next test failure and fix it.
I don't know how those of you who kick and scream and fight and claw about how unit testing will increase your work load manage to accomplish anything! How do you know when your code is correct? I certainly know that without the road map my tests provide I'd be incredibly discouraged and frustrated.
Wednesday, August 27. 2008
I'm a freak about unit tests. In fact I often enjoy writing the tests more than I enjoy writing the actual production code. Seven years ago when first learning about unit tests in my day job (coding in perl with a home grown test framework). I decided to experiment with them in python. Starting with the built in unit test framework, I quickly found that I didn't like it. It didn't work the way I thought it should work and for me, made testing more difficult than it should be. I went in search of something that worked more like I do.
That search led to Codespeak's py.test. It works the way I do, no setup required, no test frameworks required, no big fixtures to build up or tear down. Write a test...
In the file
In the file
I can now run
py.testand it will find my test and run it for me reporting any errors.
As I started using PubSub, I ran into some new test issues for me, just how do you effectively test that messages were being sent or received when you believed they should be. I tinkered with it for a while, and eventually came up with the following template for my tests...
This test method is part of a test class that handles all the setup and teardown functionality, setting the initial state for each one of the test methods in the class.
One question you might ask about the above is why do I assert that attribute set on line 10 has the correct value on line 11. I do it because MsgObject doesn't just set the attribute, it does other things and since it does other things, it is quite likely that at some point in my code's life I will accidentally delete the line that actually sets the attribute, and I'd like to have my tests fail if I do so.
I like to think I write reasonably good code. I think everyone likes to think that they write good code. Of course I've always thought I wrote good code and I look at some of the stuff I wrote several years ago and cringe. Sometimes that happens when I look at code I wrote a month or so ago. Such is the case for me and GUI code I wrote prior to my learning about PubSub.
I had my View in one module and my Model in another (not quite sure where that pesky Controller got to). Yet my code had the two inextricably linked. Everyone one of my main GUI classes had references to the two main objects in the Model. Every one of those classes called methods directly on the Model and while it worked, it was becoming very difficult to maintain. Then there was a discussion about this very subject on the wxPython mailing list and I heard about PubSub for the first time (thanks Chris!).
I started messing around with it and had the View communicating with the Model in no time. The problem was the Model wasn't communicating back. Then there was another discussion on the mailing list and someone (thanks Josiah!) said doing a tiny bit of meta-programming to make an object automatically send a message when one of its attributes was set would make message passing even easier. I thought that was a wonderful idea and came up with the following class to help me do that.
All my classes that have attributes that need to be reflected in the View inherit from MsgObject and then the View simply subscribes to the topic '<classname>.update.<attribute_name>', and update themselves.
I decided to write my own Dungeons & Dragons character generator when the ones I found either looked clunky, or didn't run on OSX, or lacked functionality I believed was required in such a tool. Since I had a bit of experience with wxPython creating my Conway's Life toy, I decided to try it on a larger toy.
If you're not familiar with character creation for D & D one of the earliest steps is to generate your character's ability scores. There are six scores with a theoretical range of 3 to 18 (think of rolling four dice, discarding the lowest number and summing the points shown on the remaining three). Those scores are then assigned to your character's abilities of Strength, Dexterity, Constitution, Intelligence, Wisdom and Charisma.
The problem I faced is that you can pick and choose which ability goes with which score and how do you present this in a usable and attractive UI? I had seen some interfaces using Radio Buttons, but they were bulky and cumbersome, so I decided to use the wx.Choice widget. The problem was that you could not disable an item in item list for a choice, and a user can only select each ability one time so what to do.
My solution to that problem is the RadioChoice widget. It allows you to create a group of wx.Choice widgets, each one starting with the same available choices, but when you make a choice on one of the widgets, that choice is removed from all of the other widgets.
This is my first "useful" widget. Who knows, it may only be useful for matching D&D abilities to scores, but then again you might find some other use for it.
The code and demo are available here...
Constructive criticism is always welcome.
Tuesday, August 26. 2008
I'm working on a project where at one point I needed to make sure that two dictionaries had the same keys. update() wouldn't work for me because I wanted new keys to have a default value. I wrote a couple of iterations of the code using for loops and eventually ended up with this two-liner using sets:
Sunday, August 24. 2008
I touched my first computer on the end of a 300 baud acoustic coupled modem at Benson Polytechnic High School in 1977. I wrote horrible code in horrible BASIC, but it was when my love of programming began. In 1982 I was a CS major at Oregon State University. I spent far too much time goofing off and far too little time studying and the CS department gave me a very polite invitation to not be a CS major any longer. My father was an itinerant Preacher, and in the winter of 1982 he was planning trip around the world to minister in various and sundry places for about six months. My parents asked if I would tag along. I did.
On that trip I read about Conway's cellular automaton simulation and was fascinated by it. It just so happened that at one of our stops in the UK there was a computer available to me (I can't remember what it was, but it did have a BASIC interpreter) and it was there that I first attempted to write my own version of life. It was not good, not very functional, but I did move my skills at writing code forward just a bit.
Several months ago, I decided I wanted to do a bit of GUI programming. I'd tinkered with PyQt, but it's support on Apple didn't "feel" as good as wxPython's support on Apple, so I started teaching myself wxPython. My first project was Conway's Life. The code is not brilliant, it is somewhat slow if the grid gets too large, but it does work, and it was a very good educational experience for me. Are there better ways to do it? I'm sure there are. I'd love to hear that feedback.
rudimentary unit tests for life.py (using py.test)
Friday, May 12. 2006
I just committed a slightly newer version of PyTestMate. If you're interested in the original announcement you can see it here.
The main new feature of this release is colour-coding of the errors. The Error Free display looks something like this:
When a test fails, the output will look something like this:
Any constructive input will be gratefully received.
There's still a lot of work to do here. PyTestMate does not gracefully handle coding errors (syntax or logical) if exceptions or failures occur, the output is very ugly. Those are the next problems for me to tackle.
Friday, April 28. 2006
For some reason pyunit and I just don't get along too well. I'm not sure why that is, we just don't, yet I love Test Driven Development. So when I read about py.testI jumped at the chance to try something new. I love py.test. It works the way I do. It's not perfect, but it meets my needs.
One of the places it lacks perfection is in comparison of long strings. py.test breaks long strings and substitutes "..." for a chunk in the middle of each string. If the place where the strings differ happens to be in that "..." well then it's kinda tough to spot where the mistake is.
Another shortcoming of the standard
is that when you're comparing something like code generated HTML vs. the readable (I hope you make it readable) HTML in your test, whitespace becomes a factor in equality and that can be painful.
I put together the following function to help with both situations:
The only downside to the above is that failure gets reported twice. Once at the call to the function, and once at the assertion. I'm not sure if there's a way to avoid that or not yet.
Wednesday, April 26. 2006
I wrote earlier about how easy it was to add support for py.test to TextMate While it worked effectively it was really ugly as it used a deprecated feature of TextMate. TextMate's default interface to Python is called PyMate. It gives very nice, very readable output from the Python interpreter. I thought that if Python output could be so pretty and readable, it should be possible to do something similar with the output from py.test.
My efforts to create such a tool are located here PyTestMate. Please be aware that while this is quite usable for me, it may or may not work for you! There are no good installation instructions yet, and you will have to configure the bundle command yourself.
Of course all the unit tests for PyTestMate were written using PyTestMate!
I would love any feedback, good, bad or indifferent. I'll enhance it as time permits, and if you have suggestions please let me know so I can add them to my todo list.
Friday, February 25. 2005
As I start learning about OS/X and working with Python on it, I keep turning up odd little things. When I'm playing with libraries I dump them willy-nilly into a directory in my home directory, and I have the
Yesterday I was attempting to import a library, and nothing I did worked. I checked all the settings and they all looked correct, but the value of
Wednesday, February 23. 2005
Before I moved to my PowerBook, I ran Gentoo Linux on an IBM ThinkPad. I have a Creative Nomad Zen Xtra MP3 player, and found some software that ran under Linux and worked with it. However it doesn't work like I do, so I started tinkering with Python, PyQt, and Python-libnjb, working up a bit of an interface that sorta-kinda started to look like what I wanted. However, that project got put on hold when I moved to my PowerBook and Mac OS/X. There's some very good software XNJB that I've been using to keep my Nomad up to date, but once again, while it works very well, it doesn't work like I do.
That all sounded like a great excuse to break out the Project I'd been working on. Getting everything to work correctly was an interesting project in itself. One of the beauties of Python is you don't have to be an expert at compiling or linking to make great use of it. Building libusb and libnjb on my PowerBook was fairly easy, but getting Python-libnjb to build caused me all sorts of grief when it came to linking. Eventually thanks to some help on the Python mailing list I got the library to build correctly. The linker command in the Makefile should look like this:
ld -bundle -flat_namespace -undefined suppress\
This built the library without any errors. However, when trying to load it in Python I got the following error:
Python 2.3.3 (#1, Aug 23 2004, 20:06:57)
I have yet to find a good solution to the above problem. At the moment the solution is a horrid kludge, creating a symlink from /lib to /sw/lib.
Wednesday, January 24. 2001
Today was a bit strange. We have a contact inside a rather large company here in town. He was able to get a chance to set up a test install of our system at his company. This was such a big deal, that all sorts of people were really excited about it.
Chris and I got on site, got our server set up, and started talking with the man who was the project lead. He started telling us about all sorts of requirements that we had not known prior to going, and that would have kept us from going and embarassing ourselves had we only known.
Well, we didn't embarass ourselves, our stuff worked as advertised, it was just totally unacceptable for their current needs. I guess I should be disapointed, but I'm not, nor are Chris and John. The trip wasn't a complete bust as we were able to do a demo of our really cool stuff for another tech guy at this large company.
We also had a major breakthrough in application delivery today. John actually ran through the office to accomplish a task today! I've never seen him do that. It was pretty cool. So, I guess the low of the bad test scenario, was balanced by the great high of this new application delivery mechanism.
Yep, it was rather strange, but we are getting used to strange around here.
On a completely different note. The only response I have gotten so far on my want ad for a Python programmer has been from a head hunter. That pretty much sucks. However, We also need a new system engineer to offload some of my work, and to learn how to deploy our tools...
I have a long relationship with my ISP. They have treated me well for the last 5 1/2 or 6 years. One of the things I like about them, and the reason I recommend them to all my clients, is the fact that I can pick up the phone and call their system engineer directly. Well, aracnet.com just got purchased by another local ISP. Their system engineer is now redundant and looking for work. We need a system engineer. He's coming in for his second interview tomorrow evening. I'll let you know how it turns out.
Wednesday, January 17. 2001
We need to hire a programmer. I need a good, experienced Python coder. Yesterday we were given permission to start the search for one, so I posted the following job announcement on our local user group list.
Avalon Technology Group, Inc. is looking for a new Python programmer to work
for its new startup company HyperLINq Technologies, Inc.
- Demonstrated excellence and skill at using Python & Tkinter
- Familiarity with object oriented design and coding
- Excellent understanding of both Linux and Windows 95/98
- Ability to work with others in a small, closely knit development group
- Ability to solve complex programming problems
It would be nice if:
- You have experience as a system administrator
- You have experience with Zope
- The position will start out as part time (20-30 hours per week) with the
opportunity to move to full time with full benefits and incentive stock
- Please send resumes and any other pertinent information to
So far, I have yet to receive a response. I don't know why, and I'm just a bit disappointed. I would have thought that there would be any number of people who would jump at the chance.
I don't know whether to blame my requirements, the initial part time nature of the job, or what. We are so new at this and I have so much to learn. I just hope I can quickly learn what was wrong with my job posting.
(Page 1 of 2, totaling 17 entries) » next page
apple applestore blackberry books civics concert d&d dvd editors faith family fanboy firefly food food grilling and recipes friends gti halo hobbies honorharrington humour hyperlinq iPod ipr law linux motorcycles movies music onmyipod oop os/x pets politics priceless programming pubsub python rant recipes religion review riding ridinggear salad society sports support technology travel unittest video games widget writing wxpython xbox360
Last entry: 2010-03-04 12:39
166 entries written
12 comments have been made