Possible bug in 1.0.4b3 tag of turbogears

The /visit/api.py file in the 1.0.4b3 tag of turbogears has this function, starting on line 177:

def encode_utf8(params):
'''
will recursively encode to utf-8 all values in a dictionnary
'''
res = dict()
for k, v in params.items():
if type(v) is dict:
res[k] = encode_utf8(v)

else:
res[k] = v.encode('utf-8')

return res

If you have a query string like ?a=1&a=2, then params has a key u’a’ that points to a list that contains u’1′ and u’2′. And encode isn’t defined for lists, so . . .

Fortunately, the /visit/api.py file in the branches/1.0 branch already has a fix for this problem, so I ran setup.py develop in my checkout directory and was back in business.

I lost so much time today figuring this out because I kept looking for the bug in my code, rather than in the framework itself. Also, the code works fine as long as the query string doesn’t have more than one value for the same key.

While I’m on the soapbox, I really wish that testutil.py would change this function:

def tearDown(self):
database.rollback_all()
for item in self._get_soClasses():
if isinstance(item, types.TypeType) and issubclass(item,
sqlobject.SQLObject) and item != sqlobject.SQLObject \
and item != InheritableSQLObject:
item.dropTable(ifExists=True)

to something sort of like this instead:

def tearDown(self):
database.rollback_all()
import copy # Probably don't actually import here, but this is just for illustration.
x = copy.copy(self.__get_soClasses()) # store a copy of the list.
x.reverse() # Now reverse it.
for item in x: # Iterate the reversed copy.
if isinstance(item, types.TypeType) and issubclass(item,
sqlobject.SQLObject) and item != sqlobject.SQLObject \
and item != InheritableSQLObject:
item.dropTable(ifExists=True)

The whole point of using self.__get_soClasses is that it looks for a list that defines the order to follow when creating tables. You can define soClasses in your model to make sure that your independent tables are created before your dependent tables.

Well, when it comes time to destroy all your tables, you should destroy the dependent tables first.

I posted this about a month ago to the turbogears trunk mailing list already.

Sidenote — if you’re one of the people that are selflessly donating your time to working on turbogears, please don’t take my rants here personally. I’m really grateful that other people are building tools and giving them away, so that I can make a living.

Published by

matt

My name is Matt Wilson. I make websites for Kiwee to pay the bills. I live in Cleveland Heights, Ohio, with my wife and son.

  • Florent Aide

    Hi Matt,

    please test the SVN (branch 1.0, revision 3866 or upper) which has a lot of fixes regarding the first error (encode_utf8). I’ll release 1.0.4b4 on Saturday night. If you find some problem you’ll have time to ping me back.

    Regarding the second issue, please could you post a ticket in our trac system with the proposed patch, and ping me back in the ML by answering the original thread with the ticket id. I _really_ have no time to work on this right now. I would have loved to release 1.0.4b4 nearly one month ago already. I swear I’ll look at this and apply it if it works 🙂

    This way you’ll get all the fixes in the next release.

    Cheers,
    Florent Aide.

  • http://gedmin.as/ Marius Gedminas

    Is there any reason you can’t do

    for item in reversed(self._get_soClasses()):

    and have to use copy.copy() instead?

  • http://tplus1.com matt

    Marius: Thanks for pointing out that I could have used reversed instead of a copy and an in-place reverse. I keep forgetting about reversed.

    Florent: I am now running the svn 1.0 branch it works beautifully. I’ll post a ticket into trac and then follow up on my original post.