<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _unapply_interception(target, ctx=None):
 """Unapply interception on input target in cleaning it. :param routine target: target from where removing an interception function. is_joinpoint(target) must be True. :param ctx: target ctx. """


    # try to get the right ctx
    if ctx is None:
        ctx = find_ctx(elt=target)

    # get previous target
    intercepted, old_ctx = get_intercepted(target)

    # if ctx is None and old_ctx is not None, update ctx with old_ctx
    if ctx is None and old_ctx is not None:
        ctx = old_ctx

    if intercepted is None:
        raise JoinpointError('{0} must be intercepted'.format(target))

    # flag to deleting of joinpoint_function
    del_joinpoint_function = False

    # if old target is a not modifiable resource
    if isbuiltin(intercepted):
        module = getmodule(intercepted)
        found = False

        # update references to target to not modifiable element in module
        for name, member in getmembers(module):
            if member is target:
                setattr(module, name, intercepted)
                found = True

        # if no reference found, raise an Exception
        if not found:
            raise JoinpointError(
                "Impossible to unapply interception on not modifiable element \
                {0}. Must be contained in module {1}".format(target, module)
            )

    elif ctx is None:
        # get joinpoint function
        joinpoint_function = _get_function(target)
        # update old code on target
        joinpoint_function.__code__ = intercepted.__code__
        # ensure to delete joinpoint_function
        del_joinpoint_function = True

    else:
        # flag for joinpoint recovering
        recover = False
        # get interception name in order to update/delete interception from ctx
        intercepted_name = intercepted.__name__
        # should we change of target or is it inherited ?
        if isclass(ctx):
            base_interception, _ = super_method(name=intercepted_name, ctx=ctx)
        else:
            base_interception = getattr(ctx.__class__, intercepted_name, None)
        # if base interception does not exist
        if base_interception is None:  # recover intercepted
            recover = True

        else:
            # get joinpoint_function
            joinpoint_function = _get_function(target)
            # get base function
            if is_intercepted(base_interception):
                base_intercepted, _ = get_intercepted(base_interception)
            else:
                base_intercepted = _get_function(base_interception)
            # is interception inherited ?
            if base_intercepted is joinpoint_function:
                pass  # do nothing
            # is intercepted inherited
            elif base_intercepted is intercepted:
                # del interception
                delattr(ctx, intercepted_name)
                del_joinpoint_function = True
            else:  # base function is something else
                recover = True

        if recover:  # if recover is required
            # new content to put in ctx
            new_content = intercepted
            if ismethod(target):  # in creating eventually a new method
                args = [new_content, ctx]
                if PY2:  # if py2, specify the ctx class
                    # and unbound method type
                    if target.__self__ is None:
                        args = [new_content, None, ctx]
                    else:  # or instance method
                        args.append(ctx.__class__)
                # instantiate a new method
                new_content = MethodType(*args)
            # update ctx with intercepted
            setattr(ctx, intercepted_name, new_content)
            joinpoint_function = _get_function(target)
            del_joinpoint_function = True

    if del_joinpoint_function:
        # delete _INTERCEPTED and _INTERCEPTED_CTX from joinpoint_function
        if hasattr(joinpoint_function, _INTERCEPTED):
            delattr(joinpoint_function, _INTERCEPTED)
            if hasattr(joinpoint_function, _INTERCEPTED_CTX):
                delattr(joinpoint_function, _INTERCEPTED_CTX)
        del joinpoint_function