##############################################################################
#
@register.tag(name = 'method_arg')
def method_arg(parser, token):
    """
    This tag allows us to call the given method with the given
    argument and set the resultant value to a variable in our context.
    ie: {% method_arg foo bar user as post %} would result in the
    variable 'post' getting the result of evaluating foo.bar(user).
    If the argument is surrounded by quotes, then it is considered a
    string and not a variable to be resolved.
    """
    try:
        tag_name, var, method_name, arg, ign, dst = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, "%r requires arguments in the " \
              "format of <variable> <methodname> <argument> as <variable>."
    if ign.lower() != "as":
        raise template.TemplateSyntaxError, "%r requires arguments in the " \
              "format of <variable> <methodname> <argument> as <variable>."
    return MethodArgNode(var, method_name, arg, dst)

class MethodArgNode(template.Node):
    """
    The template node sub-class that does the work of looking up the
    method you wish to invoke in your template, resolving the variable
    to pass to it and setting the resultant value in the template's
    context.
    """
    def __init__(self, var, method_name, arg, dst):
        self.var = var
        self.method_name = method_name
        self.arg = arg
        self.dest = dst

    def render(self, context):
        try:
            obj = resolve_variable(self.var, context)
            if hasattr(obj, self.method_name) and \
               isinstance(getattr(obj, self.method_name), MethodType):
                if self.arg[0] == self.arg[-1] and self.arg[0] in ('"', "'"):
                    context[self.dest] = \
                                getattr(obj, self.method_name)(self.arg[1:-1])
                else:
                    context[self.dest] = getattr(obj, self.method_name)\
                                         (resolve_variable(self.arg, context))
        except:
            # render() should never raise any exception. If something goes
            # wrong we need to log it somewhere else, not chuck it up the
            # call stack.
            #
            raise
            pass
        return ""