dir2.py
84 lines
| 2.2 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r2498 | # encoding: utf-8 | ||
"""A fancy version of Python's builtin :func:`dir` function. | ||||
""" | ||||
Thomas Kluyver
|
r22148 | # Copyright (c) IPython Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||||
Thomas Kluyver
|
r13353 | |||
Thomas Kluyver
|
r22148 | import inspect | ||
David Straub
|
r24071 | import types | ||
Brian Granger
|
r2498 | |||
Jeffrey Tratner
|
r12965 | |||
def safe_hasattr(obj, attr): | ||||
"""In recent versions of Python, hasattr() only catches AttributeError. | ||||
This catches all errors. | ||||
""" | ||||
try: | ||||
getattr(obj, attr) | ||||
return True | ||||
except: | ||||
return False | ||||
Brian Granger
|
r2498 | def dir2(obj): | ||
"""dir2(obj) -> list of strings | ||||
Extended version of the Python builtin dir(), which does a few extra | ||||
Anthony Sottile
|
r21849 | checks. | ||
Brian Granger
|
r2498 | |||
This version is guaranteed to return only a list of true strings, whereas | ||||
dir() returns anything that objects inject into themselves, even if they | ||||
are later not really valid for attribute access (many extension libraries | ||||
have such bugs). | ||||
""" | ||||
# Start building the attribute list via dir(), and then complete it | ||||
# with a few extra special-purpose calls. | ||||
sunny
|
r16549 | try: | ||
words = set(dir(obj)) | ||||
sunny
|
r16653 | except Exception: | ||
sunny
|
r16549 | # TypeError: dir(obj) does not return a list | ||
words = set() | ||||
Brian Granger
|
r2498 | |||
Paul Ivanov
|
r22998 | if safe_hasattr(obj, '__class__'): | ||
words |= set(dir(obj.__class__)) | ||||
Brian Granger
|
r2498 | # filter out non-string attributes which may be stuffed by dir() calls | ||
# and poor coding in third-party modules | ||||
Srinivas Reddy Thatiparthy
|
r23037 | words = [w for w in words if isinstance(w, str)] | ||
Tim Couper
|
r6310 | return sorted(words) | ||
Thomas Kluyver
|
r22148 | |||
def get_real_method(obj, name): | ||||
"""Like getattr, but with a few extra sanity checks: | ||||
David Straub
|
r24071 | - If obj is a class, ignore everything except class methods | ||
Thomas Kluyver
|
r22148 | - Check if obj is a proxy that claims to have all attributes | ||
- Catch attribute access failing with any exception | ||||
- Check that the attribute is a callable object | ||||
Returns the method or None. | ||||
""" | ||||
try: | ||||
canary = getattr(obj, '_ipython_canary_method_should_not_exist_', None) | ||||
except Exception: | ||||
return None | ||||
if canary is not None: | ||||
# It claimed to have an attribute it should never have | ||||
return None | ||||
try: | ||||
m = getattr(obj, name, None) | ||||
except Exception: | ||||
return None | ||||
David Straub
|
r24071 | if inspect.isclass(obj) and not isinstance(m, types.MethodType): | ||
return None | ||||
Thomas Kluyver
|
r22148 | if callable(m): | ||
return m | ||||
return None | ||||