Scholrly is working on a Neo4j/Django integration layer based on neo4j.py 's Django support. The layer emulates Django's ORM at the model level, so it has to do all sorts of metaprogramming backflips.
My personal favorite result of those acrobatics came up last week. Running our test suite, I was getting some interesting results. Here are the relevant, simplified tests.
def test_int_property():
class Person(neo4django.NodeModel):
age = neo4django.IntegerProperty()
sandra = Person(age=21)
sandra.save()
assert age == 21, 'You told me you were 21!'
def test_str_property():
class Person(neo4django.NodeModel):
name = neo4django.StringProperty()
don = Person(name='Don')
don.save()
assert don.name == 'Don', 'Don isn't who he says he is.'
The first test ran fine. The second didn't, failing with something like
Traceback (most recent call last):
File "/home/matt/python_envs/neo4django/lib/python2.6/site-packages/nose/case.py", line 187, in runTest
self.test(*self.arg)
File "/home/matt/neo4django/neo4django/tests/tests.py", line 242, in test_str_property
don.save()
...
File "/home/matt/neo4django/neo4django/properties.py", line 272, in _save_
prop = properties[key]
KeyError: 'age'
Um. Okay, what happened? Clearly the Person class shouldn't have a defined 'age' property. If right now, you're screaming "it's because you screwed up in some metaclass!", well, we both know you just read the title of the post, so shush.
Yes, yes, there was a bug in a metaclass. But the interesting thing in this case isn't the particular bug, but that playing with metaclasses allowed me to invalidate a core assumption made in our test suite- that defining classes in different test cases would help preserve test independence. In fact, it did just the opposite- any test case that defined a class with a shared name failed, unless it was the first case to do so.
One of the (now) obvious dangers of metaclasses is the violation of developer expectations. What appeared to be a straight-forward test suite became an overly invasive measurement tool- and for a couple days we were at the mercy of the 244th fundamental of design- the uncertainty principle.
