Catch some pathological cases inside oinspect

Third party code that overrides attribute access can mess up some of our introspection code, because `hasattr()` since Python 3.2 only catches `AttributeError`. This uses a `safe_hasattr` function, which will catch any exception raised by attribute access.

Closes #2577