rootpy/rootpy — pull request #355 by pwaller (2013-06-26 14:10:19+00:00)
Title: `snake_case_methods` breaks descriptors

This bug caused a regression in 01edd2d99feede77e74b3ae87a2c95ed0bdf33dd. Compare the output of this commit and the one beforehand:

```
[01edd2^] $ python -c "import rootpy.ROOT as R; print R.File.open"

[01edd2] $ python -c "import rootpy.ROOT as R; print R.File.open"

```

The latter is not usable and breaks my code.

# What's the problem?

The problem is due to the way that [`snake_case_methods`](https://github.com/rootpy/rootpy/blob/master/rootpy/decorators.py#L155) (SCM) works. I thought I had fixed this in 29626c704158eab8cfcf00963b1627e11b4d04bd, but apparently not.

The root cause is in the way that SCM aliases existing methods. Prior to 29626c7, it did this by `getattr`ing the target function and `setattr`'ing it on the target class. The problem is that `getattr` actually "dereferences" the descriptor (`__get__`) of target function. That means that `staticmethod`s become ordinary functions, which then get tacked onto the target class and suddenly they look like unbound methods.

I tried to fix this by making it a `__dict__` lookup on the target class, which prevents the descriptor machinary from kicking in, but then 01edd2d shows that this isn't sufficient, because of inheritance - the target function might not be in the `cls.__dict__` but in one of its super classes - so we need to visit the super classes in order according to the mro, and look inside the `__dict__` of each one.

# What's needed to prevent this from happening again?

Two test cases:

1. Check that File.open works correctly
2. Check that `snake_case_methods` does the right thing.