def VisibleMembers(component, class_attrs=None, verbose=False): """Returns a list of the members of the given component. If verbose is True, then members starting with _ (normally ignored) are included. Args: component: The component whose members to list. class_attrs: (optional) If component is a class, you may provide this as: inspectutils.GetClassAttrsDict(component). If not provided, it will be computed. If provided, this determines how class members will be treated for visibility. In particular, methods are generally hidden for non-instantiated classes, but if you wish them to be shown (e.g. for completion scripts) then pass in a different class_attr for them. verbose: Whether to include private members. Returns: A list of tuples (member_name, member) of all members of the component. """ if isinstance(component, dict): members = component.items() else: members = inspect.getmembers(component) # If class_attrs has not been provided, compute it. if class_attrs is None: class_attrs = inspectutils.GetClassAttrsDict(component) return [(member_name, member) for member_name, member in members if MemberVisible(component, member_name, member, class_attrs=class_attrs, verbose=verbose)]
def _DictAsString(result, verbose=False): """Returns a dict as a string. Args: result: The dict to convert to a string verbose: Whether to include 'hidden' members, those keys starting with _. Returns: A string representing the dict """ # We need to do 2 iterations over the items in the result dict # 1) Getting visible items and the longest key for output formatting # 2) Actually construct the output lines class_attrs = inspectutils.GetClassAttrsDict(result) result_visible = { key: value for key, value in result.items() if completion.MemberVisible(result, key, value, class_attrs=class_attrs, verbose=verbose) } if not result_visible: return '{}' longest_key = max(len(str(key)) for key in result_visible.keys()) format_string = '{{key:{padding}s}} {{value}}'.format(padding=longest_key + 1) lines = [] for key, value in result.items(): if completion.MemberVisible(result, key, value, class_attrs=class_attrs, verbose=verbose): line = format_string.format(key=str(key) + ':', value=_OneLineResult(value)) lines.append(line) return '\n'.join(lines)
def MemberVisible(component, name, member, class_attrs=None, verbose=False): """Returns whether a member should be included in auto-completion or help. Determines whether a member of an object with the specified name should be included in auto-completion or help text(both usage and detailed help). If the member name starts with '__', it will always be excluded. If it starts with only one '_', it will be included for all non-string types. If verbose is True, the members, including the private members, are included. When not in verbose mode, some modules and functions are excluded as well. Args: component: The component containing the member. name: The name of the member. member: The member itself. class_attrs: (optional) If component is a class, provide this as: inspectutils.GetClassAttrsDict(component). If not provided, it will be computed. verbose: Whether to include private members. Returns A boolean value indicating whether the member should be included. """ if isinstance(name, six.string_types) and name.startswith('__'): return False if verbose: return True if member in (absolute_import, division, print_function): return False if isinstance(member, type(absolute_import)) and six.PY34: return False if inspect.ismodule(member) and member is six: # TODO(dbieber): Determine more generally which modules to hide. return False if inspect.isclass(component): # If class_attrs has not been provided, compute it. if class_attrs is None: class_attrs = inspectutils.GetClassAttrsDict(class_attrs) or {} class_attr = class_attrs.get(name) if class_attr: # Methods and properties should only be accessible on instantiated # objects, not on uninstantiated classes. if class_attr.kind in ('method', 'property'): return False # Backward compatibility notes: Before Python 3.8, namedtuple attributes # were properties. In Python 3.8, they have type tuplegetter. tuplegetter = getattr(collections, '_tuplegetter', type(None)) if isinstance(class_attr.object, tuplegetter): return False if (six.PY2 and inspect.isfunction(component) and name in ('func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name')): return False if (six.PY2 and inspect.ismethod(component) and name in ('im_class', 'im_func', 'im_self')): return False if isinstance(name, six.string_types): return not name.startswith('_') return True # Default to including the member
def HasCustomStr(component): """Determines if a component has a custom __str__ method. Uses inspect.classify_class_attrs to determine the origin of the object's __str__ method, if one is present. If it defined by `object` itself, then it is not considered custom. Otherwise it is. This means that the __str__ methods of primitives like ints and floats are considered custom. Objects with custom __str__ methods are treated as values and can be serialized in places where more complex objects would have their help screen shown instead. Args: component: The object to check for a custom __str__ method. Returns: Whether `component` has a custom __str__ method. """ if hasattr(component, "__str__"): class_attrs = inspectutils.GetClassAttrsDict(type(component)) or {} str_attr = class_attrs.get("__str__") if str_attr and str_attr.defining_class is not object: return True return False