« December 2008 | Main | February 2009 »

January 14, 2009

Resolver One

I'm in the frustrating position of having spent a fair chunk of last year doing cool stuff with Resolver One, a python-based spreadsheet app. Frustrating, because the manufacturers have started handing out prizes for interesting resolver-based projects -- and I'm in no position to talk about, let alone open-source, most of what I've been doing.

Instead, I'll just repeat that I love Resolver -- it's good enough to impress me despite being closed-source, and Windows-only*, and mainly aimed at financial number-crunchers in the City.

The main appeal for me is having python tightly integrated into a spreadsheet. Lambdas and list comprehensions are a natural fit for spreadsheets, to the extent that it's painful trying to re-learn how to do things in Excel or OpenOffice. Here's a simple example for adding up wages:


1 =SUM([row['Salary'] for row in <Employees>.ContentRows if row['job'] == 'Postman')

But, since the expression in every cell can be an arbitrarily-complex python expression, you can do much more intricate calculations in the same idiom. Plus Reslver is built on IronPython, which gives you the ability to use .NET libraries as well as python ones. And you can export your spreadsheet as a python class, letting you plug it into any other application you fancy. And, and...

Anyway, that's the end of enthusiasm. Back to grumbling about politics shortly, no doubt.

* I'm still a dedicated Ubuntu/Debian user. But Amazon, flexiscale or GoGrid will rent you a Windows server for ~10c/hr, so I've only been marginally inconvenienced by Resolver being Windows-only.

January 12, 2009

pycallgraph

[perhaps of faint interest to python programmers, certainly not to anybody else]
I've just found pycallgraph, which makes it easy to visualize the structure of function calls within python code.
This is immensely useful for debugging, and for getting a feel for the structure of a program. It's something you could theoretically already do with epydoc and a profiler, but that's always seemed like a lot of work for little return.
With pycallgraph, it takes a couple of lines:
1 import pycallgraph
2 pycallgraph.start_trace()
3 #...code to be graphed goes here
4 pycallgraph.make_dot_graph('test.png')
5

That's still a lot of typing, though, when I really only want it for a quick picture of whatever is currently baffling me. pycallgraph have missed an opportunity to rewrite it as a decorator:
 1 import pycallgraph
 2
 3 def callgraph(filename = '/tmp/callgraph.png'):
 4     def argwrapper(func):
 5         def callwrapper(*args, **kwargs):
 6             if callwrapper.already_called:
 7                 return func(*args, **kwargs)
 8             callwrapper.already_called = True
 9             pycallgraph.start_trace(reset = False)
10             result = func(*args, **kwargs)
11             pycallgraph.stop_trace()
12             pycallgraph.make_dot_graph(filename)
13             return result
14         callwrapper.already_called = False
15         return callwrapper
16     return argwrapper

This lets me generate a call-graph of any function, by popping a one-line decorator onto it:
1 @callgraph('/tmp/callgraph.png')
2 def myfunc():
3     #code here

The other advantage here is that I generally only want to generate the graph once, when the function is first called. Hence the use of afunction attribute, already_called, as a flag to short-circuit past the call-graph on subsequent runs.