def endpoint(self, *args):
<EOL>def decorator(func):<EOL><INDENT>func_name = func.__name__<EOL>func_name = func_name.replace("<STR_LIT>", "<STR_LIT>")<EOL>actions = func_name.split("<STR_LIT:_>")<EOL>cmd_parser = None<EOL>sub = self.subparsers<EOL>wcount = <NUM_LIT:0><EOL>for word in actions:<EOL><INDENT>parser_name = '<STR_LIT:_>'.join(actions[:wcount+<NUM_LIT:1>])<EOL>if self.parsers.has_key(parser_name):<EOL><INDENT>cmd_parser = self.parsers[parser_name]<EOL><DEDENT>else:<EOL><INDENT>cmd_parser = sub.add_parser(word)<EOL>self.parsers[parser_name] = cmd_parser<EOL><DEDENT>if wcount != len(actions) - <NUM_LIT:1>:<EOL><INDENT>if self.parsers.has_key("<STR_LIT>"+parser_name):<EOL><INDENT>sub = self.parsers["<STR_LIT>"+parser_name]<EOL><DEDENT>else:<EOL><INDENT>sub = cmd_parser.add_subparsers()<EOL>self.parsers["<STR_LIT>"+parser_name] = sub<EOL><DEDENT><DEDENT>wcount += <NUM_LIT:1><EOL><DEDENT>cmd_parser.set_defaults(func=func)<EOL>for argument in args:<EOL><INDENT>if type(argument) == Argument:<EOL><INDENT>cmd_parser.add_argument(*argument.args, **argument.kwargs)<EOL><DEDENT>elif type(argument) == ExclusiveGroup:<EOL><INDENT>group = cmd_parser.add_mutually_exclusive_group(required=argument.required)<EOL>for arg in argument.args:<EOL><INDENT>group.add_argument(*arg.args, **arg.kwargs)<EOL><DEDENT><DEDENT><DEDENT>def inner(*args, **kwargs):<EOL><INDENT>return func(*args, **kwargs)<EOL><DEDENT>return inner<EOL><DEDENT>return decorator<EOL>
endpoint: Decorates a function to make it a CLI endpoint

        The function must be called do_<some>_<action> and accept one 'args'
        parameter. It will be converted into a ./cli some action commandline
        endpoint.

        A set of Arguments can be passed to the decorator, the syntax is the
        same than the argparse add_argument function.