dir2.py
89 lines
| 2.8 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r2498 | # encoding: utf-8 | ||
"""A fancy version of Python's builtin :func:`dir` function. | ||||
""" | ||||
#----------------------------------------------------------------------------- | ||||
Matthias BUSSONNIER
|
r5390 | # Copyright (C) 2008-2011 The IPython Development Team | ||
Brian Granger
|
r2498 | # | ||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#----------------------------------------------------------------------------- | ||||
#----------------------------------------------------------------------------- | ||||
# Imports | ||||
#----------------------------------------------------------------------------- | ||||
Thomas Kluyver
|
r13353 | from .py3compat import string_types | ||
Brian Granger
|
r2498 | #----------------------------------------------------------------------------- | ||
# Code | ||||
#----------------------------------------------------------------------------- | ||||
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 get_class_members(cls): | ||
ret = dir(cls) | ||||
Jeffrey Tratner
|
r12965 | if safe_hasattr(cls, '__bases__'): | ||
Jörgen Stenarson
|
r4113 | try: | ||
bases = cls.__bases__ | ||||
except AttributeError: | ||||
# `obj` lied to hasattr (e.g. Pyro), ignore | ||||
pass | ||||
else: | ||||
for base in bases: | ||||
ret.extend(get_class_members(base)) | ||||
Brian Granger
|
r2498 | return ret | ||
def dir2(obj): | ||||
"""dir2(obj) -> list of strings | ||||
Extended version of the Python builtin dir(), which does a few extra | ||||
checks, and supports common objects with unusual internals that confuse | ||||
dir(), such as Traits and PyCrust. | ||||
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. | ||||
MinRK
|
r16678 | try: | ||
words = set(dir(obj)) | ||||
except Exception: | ||||
# TypeError: dir(obj) does not return a list | ||||
words = set() | ||||
Brian Granger
|
r2498 | |||
Jeffrey Tratner
|
r12965 | if safe_hasattr(obj, '__class__'): | ||
Tim Couper
|
r6310 | #words.add('__class__') | ||
words |= set(get_class_members(obj.__class__)) | ||||
Brian Granger
|
r2498 | |||
Tim Couper
|
r6310 | # for objects with Enthought's traits, add trait_names() list | ||
# for PyCrust-style, add _getAttributeNames() magic method list | ||||
for attr in ('trait_names', '_getAttributeNames'): | ||||
Jeffrey Tratner
|
r12965 | try: | ||
func = getattr(obj, attr) | ||||
if callable(func): | ||||
words |= set(func()) | ||||
except: | ||||
# TypeError: obj is class not instance | ||||
pass | ||||
Brian Granger
|
r2498 | |||
# filter out non-string attributes which may be stuffed by dir() calls | ||||
# and poor coding in third-party modules | ||||
Thomas Kluyver
|
r13353 | words = [w for w in words if isinstance(w, string_types)] | ||
Tim Couper
|
r6310 | return sorted(words) | ||