<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def _stub_attr(obj, attr_name):
    '''
    Stub an attribute of an object. Will return an existing stub if
    there already is one.
    '''
    # Annoying circular reference requires importing here. Would like to see
    # this cleaned up. @AW
    from .mock import Mock

    # Check to see if this a property, this check is only for when dealing
    # with an instance. getattr will work for classes.
    is_property = False

    if not inspect.isclass(obj) and not inspect.ismodule(obj):
        # It's possible that the attribute is defined after initialization, and
        # so is not on the class itself.
        attr = getattr(obj.__class__, attr_name, None)
        if isinstance(attr, property):
            is_property = True

    if not is_property:
        attr = getattr(obj, attr_name)

    # Return an existing stub
    if isinstance(attr, Stub):
        return attr

    # If a Mock object, stub its __call__
    if isinstance(attr, Mock):
        return stub(attr.__call__)

    if isinstance(attr, property):
        return StubProperty(obj, attr_name)

    # Sadly, builtin functions and methods have the same type, so we have to
    # use the same stub class even though it's a bit ugly
    if inspect.ismodule(obj) and isinstance(attr, (types.FunctionType,
                                            types.BuiltinFunctionType,
                                            types.BuiltinMethodType)):
        return StubFunction(obj, attr_name)

    # In python3 unbound methods are treated as functions with no reference
    # back to the parent class and no im_* fields. We can still make unbound
    # methods work by passing these through to the stub
    if inspect.isclass(obj) and isinstance(attr, types.FunctionType):
        return StubUnboundMethod(obj, attr_name)

    # I thought that types.UnboundMethodType differentiated these cases but
    # apparently not.
    if isinstance(attr, types.MethodType):
        # Handle differently if unbound because it's an implicit "any instance"
        if getattr(attr, 'im_self', None) is None:
            # Handle the python3 case and py2 filter
            if hasattr(attr, '__self__'):
                if attr.__self__ is not None:
                    return StubMethod(obj, attr_name)
            if sys.version_info.major == 2:
                return StubUnboundMethod(attr)
        else:
            return StubMethod(obj, attr_name)

    if isinstance(attr, (types.BuiltinFunctionType, types.BuiltinMethodType)):
        return StubFunction(obj, attr_name)

    # What an absurd type this is ....
    if type(attr).__name__ == 'method-wrapper':
        return StubMethodWrapper(attr)

    # This is also slot_descriptor
    if type(attr).__name__ == 'wrapper_descriptor':
        return StubWrapperDescriptor(obj, attr_name)

    raise UnsupportedStub(
        "can't stub %s(%s) of %s", attr_name, type(attr), obj)