Thursday, February 27, 2014

A really dumb error and hard to find...

Just a little post about a stupid mistake to keep the blog alive.

So I am to the point of beginning unit-test of another module. (So far there are two (2!!!) modules that are coded and have unit-test drivers that invoke 100% code coverage and they run, ta-daa!) So this will be the third. (Third in a series of a-number-too-large-to-contemplate-on-an-empty-stomach.)

So worddata.py is the first module that needs access to resources created by The Book, the thing that holds all resources unique to one document/book. Specifically it needs access to the metadata manager so it can register readers and writers for four kinds of metadata, and access to a spellcheck object, and to The Document, an enhanced QTextDocument that is the data model for the editor.

Which meant I had to create some kind of stubbed-out Book class that could create those three resources (editdata and metadata are the two coded-and-running modules, and spellcheck is another stub so far), and return references to them on request. So I did, it's 20 lines of code starting with the usual stuff,

class Book(QObject):
    def _init_(self, main_window): #TODO: API?
        super().__init__(main_window)
        #
        # Create the metadata manager
        #
        self.metamgr = metadata.MetaMgr(self)
        etc etc...

Notice anything wrong? I didn't, and my fingers typed it.

So execute this puppy, the line the_book = book.Book(fake_main_window) is executed instantly but later code fails because "Book object has no attribute 'metamgr'". WTF? It's right there, second line in the initializer. Put a breakpoint on that line, sho nuff it is never executed.

Really, it took me ten minutes to notice the shortage of underscores on _init_. Of course in Python _init_ is a valid function name. It just won't be called to initialize a new object... You might ask, how could I get it wrong for my own class but call the correct name when initializing the super-class? Because Wing IDE recognizes "super()." and pops up a list with the only two options, "__class__" and "__init__" and I just blindly clicked the one I wanted.

OK while I am venting, before I could even get to this point, I had to solve another issue. The worddata module depends critically on blist.sorteddict, but the "from blist import sorteddict" statement failed. No blist installed. Oh right, I tried it out under Python 2.7; need to install it in Python 3.3 now, too. "pip install blist" fails with obscure error message. Google around and search SO and figure out it must be back-level setuptools. "pip install -U setuptools" fails with a different, obscure message. More googling, at least an hour wasted. However, "easy_install -U setuptools" does work, after which "pip install blist" works.

And may I say the current state of python distribution tools is horrendous! There is pip and easy_install which rely on setuptools or distutils or distutils2, and there are zips and eggs and now wheels, and numpy is off on its own thing with conda... argle bargle. Piffle.

No comments: