Friday, July 25, 2008

I've discovered that my seat-of-the-pants install of ATLAS a week or so ago caused a from-scratch build of NumPy to be broken. :/ So I'm now burning up some time doing a correct install of ATLAS/LAPACK, and maybe I'll actually be able to "import numpy" by the end of the day. (Yes, my machine is that slow).

The monkeypatching madness is now gone from numpy.testing, as are the decorators. There have been some minor additions/changes to support SciPy tests (like moving print_assert_equal to NumPy so there don't have to be 3 separate but identical implementations in SciPy) and make the output more informative (show NumPy/SciPy/Python versions and say which tests are being run).

I submitted patches for the __mul__ and __mod__ problems of chararray, since the fixes would actually change the current behavior of the class, and I figure that's best looked at by others. This presumes that somebody's actually using the class.... ;) The 1.1.x development should be done soon, and then there should be plenty of eyes on the 1.2 defects, so the fix should still fit into the GSoC schedule.

Jarrod also asked if I could standardize the NumPy imports (as "import numpy as np") whenever I run across them, so I've been doing that a little this week in SciPy and NumPy. As soon as I can get my ATLAS/LAPACK issue sorted out, and I can be sure I haven't broken anything, I'll be checking some more of those changes in.

I'm also cleaning up the SciPy test output. Currently it's littered with deprecation warnings and (apparently) debugging output from the libraries.

Finally, since the deadline is in sight, I figured I should spend some time on the final documentation. I've got some scripts hacked together to automatically generate HTML tables (for overly detailed reports) and diff files from svn + numpy/scipy-svn mailing lists, which should take care of the bulk of the tedious work (which, for some reason, I did manually last year...).

Thursday, July 17, 2008

SciPy has been switched over to use numpy.testing, scipy.testing has been removed, and it seems like everything is ok with the unit tests. Unlike NumPy, SciPy doesn't import all its subpackages on "import scipy", so the doctests need some slightly different execution context rules. Right now it looks like tests will have the module in which they are declared made available to them. So, for example, a doctest for scipy.linalg.qr will have linalg available in its context (an implicit "from scipy import linalg"). Of course this means there's a ton of SciPy doctests that need to be updated so that they'll run again.

The monkeypatching of the nose doctest plugin in numpy.testing.nosetester, which was originally a method or two, has gotten a little out of hand (as pointed out by others on the numpy-discussion list), so I'm in the process of changing over to use a new plugin (subclassed from the nose doctest plugin, numpy.plugins.doctest.Doctest). I'm also going to replace the decorators used to write the NoseTester method docstrings; since there's no other decorators used in NumPy, I'm not going to be the one that adds them. ;) Hopefully all that should be done tomorrow.

The __mul__ issue for defchararray was interesting; it appears if you pass a NumPy integer type to ndarray.__new__ as the itemsize argument, it uses the itemsize of the integer object rather than the value held by it, so (on my 32-bit machine) this meant that the return array always used an itemsize of 4 bytes. I'm not sure if this behavior is intentional.

Tuesday, July 8, 2008

Alright, so I didn't spend the entire week looking into the NumPy test environment pollution that occurs when doctests are run. I wanted to write some new tests to improve coverage, so I had to finish updating all the docstrings to run under the sanitized namespace, and get a more useful indication of coverage. That was a little tedious, but not difficult. I had to write a short script to generate annotated NumPy source (I didn't see any easy way to make nose do it), since the default coverage output--a list of uncovered line numbers--is impossible to use. For me, anyway.

Since nobody had suggested any specific bits of NumPy that they thought deserved more coverage, I just started slogging through the annotated source and looked for big blocks of uncovered code. There weren't any tests for chararray, so I started there.

The __mul__ operator doesn't seem to act right; string results that should be longer than 4 characters seem to get truncated (the resulting array dtype is S4 for some reason). The __mod__ operator doesn't seem to act like I'd expect either, but at the moment I'm willing to chalk it up to not knowing enough about how NumPy does things. So I'm off to go read more...

Tuesday, July 1, 2008

Test environment pollution

For some wonderful reason, running doctests along with the unit tests pollutes the test environment and causes tests to fail (these same tests pass when doctests are not run). So figuring out this tangled mess of execution context looks to be a significant part of what I'll be doing the rest of the week. Random thoughts and information related to these issues follow. :)

I found that I could specify a "sanitized" globals dictionary for the doctests (in the loadTestsFromModule method that's been monkeypatched onto nose.plugins.doctests.Doctest), which, as far as I can tell, has the desired effect of simulating running the doctests in a Python that's been started up and had "import numpy as np" executed. This helps prevent doctests from depending on things that might have been imported into the module where they live, locally defined functions, etc.

Some of the tests make changes that affect other tests, like the doctests in lib/ that use numpy.set_printoptions to change the display precision in order to make test output predictable. I can monkeypatch an afterContext method onto nose.plugins.doctests.Doctest to restore the original state, but this seems like a fragile way to do things, since I have to code restoration of everything that might get changed. (At least it works, though.)

Somehow, when doctests are run, the memmap module replaces the memmap class in the execution context of the tests, and so they fail. I really don't know how that's happening yet.