Issue 1007: [py3k] Fix dumbdbm, which fixes test_shelve (for me); instrument other tests so we catch this sooner (and more directly) (original) (raw)

THIS PATCH IS FOR PYTHON 3000. (There's currently no Python 3000 entry in the "Versions" list.)

As of revision 57341 (only a couple hours old as of this writing), test_shelve was failing on my machine. This was because I didn't have any swell databases available, so anydbm was falling back to dumbdbm, and dumbdbm had a bug. In Py3k, dumbdbm's dict-like interface now requires byte objects, which it internally encodes to "latin-1" then uses with a real dict. But dumbdbm.contains was missing the conversion, so it was trying to use a bytes object with a real dict, and that failed with an error (as bytes objects are not hashable). This patch fixes dumbdbm.contains so it encodes the key, fixing test_shelve on my machine.

But there's more! Neil Norvitz pointed out that test_shelve didn't fail on his machine. That's because dumbdbm is the last resort of anydbm, and he had a superior database module available. So the regression test suite was really missing two things:

* test_dumbdbm should test dumbdbm.__contains__.
* test_anydbm should test all the database modules available, not

merely its first choice.

So this patch also adds test_write_contains() to test_dumbdbm, and a new external function to test_anydbm: dbm_iterate(), which returns an iterator over all database modules available to anydbm, and internally forces anydbm to use that database module, restoring anydbm to its first choice when it finishes iteration. I also renamed _delete_files() to delete_files() so it could be the canonical dbm cleanup function for other tests.

While I was at it, I noticed that test_whichdbm.py did a good job of testing all the databases available, but with a slightly odd approach: it iterated over all the possible databases, and created new test methods--inserting them into the class object--for each one that was available. I changed it to use dbm_iterate() and delete_files() from test.test_anydbm, so that that logic can live in only one place. I didn't preserve the setattr() approach; I simply iterate over all the modules and run the tests inside one conventional method.