def clean_attributes(obj, include_props: bool = False) -> Dict[str, Any]:
    """
    Determine which attributes of the given object should be enumerated for
    storage and/or display in UI. Returns a dict of those attributes and their
    values.

    For enumerating contents of objects that do not support utility classes like
    pydantic, we use this method to guess what should be enumerated when
    serializing/displaying.

    If `include_props` is True, will produce attributes which are properties;
    otherwise those will be excluded.
    """

    keys = dir(obj)

    ret = {}

    for k in keys:
        if k.startswith("__"):
            # These are typically very internal components not meant to be
            # exposed beyond immediate definitions. Ignoring these.
            continue

        if include_props and k.startswith("_") and k[1:] in keys:
            # Objects often have properties named `name` with their values
            # coming from `_name`. This check lets avoid including both the
            # property and the value.
            continue

        try:
            v = safe_getattr(obj, k, get_prop=include_props)

            if isinstance(v, python_utils.OpaqueWrapper):
                # Don't expose the contents of opaque wrappers.
                continue

            ret[k] = v

        except Exception as e:
            logger.debug(str(e))
            logger.debug(str(e.__traceback__))

    return ret

    Determine which attributes of the given object should be enumerated for
    storage and/or display in UI. Returns a dict of those attributes and their
    values.

    For enumerating contents of objects that do not support utility classes like
    pydantic, we use this method to guess what should be enumerated when
    serializing/displaying.

    If `include_props` is True, will produce attributes which are properties;
    otherwise those will be excluded.
    
src/core/trulens/core/utils/pyschema.py