test_commands.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. # -*- coding: utf-8 -*-
  2. import re
  3. import click
  4. def test_other_command_invoke(runner):
  5. @click.command()
  6. @click.pass_context
  7. def cli(ctx):
  8. return ctx.invoke(other_cmd, arg=42)
  9. @click.command()
  10. @click.argument("arg", type=click.INT)
  11. def other_cmd(arg):
  12. click.echo(arg)
  13. result = runner.invoke(cli, [])
  14. assert not result.exception
  15. assert result.output == "42\n"
  16. def test_other_command_forward(runner):
  17. cli = click.Group()
  18. @cli.command()
  19. @click.option("--count", default=1)
  20. def test(count):
  21. click.echo("Count: {:d}".format(count))
  22. @cli.command()
  23. @click.option("--count", default=1)
  24. @click.pass_context
  25. def dist(ctx, count):
  26. ctx.forward(test)
  27. ctx.invoke(test, count=42)
  28. result = runner.invoke(cli, ["dist"])
  29. assert not result.exception
  30. assert result.output == "Count: 1\nCount: 42\n"
  31. def test_auto_shorthelp(runner):
  32. @click.group()
  33. def cli():
  34. pass
  35. @cli.command()
  36. def short():
  37. """This is a short text."""
  38. @cli.command()
  39. def special_chars():
  40. """Login and store the token in ~/.netrc."""
  41. @cli.command()
  42. def long():
  43. """This is a long text that is too long to show as short help
  44. and will be truncated instead."""
  45. result = runner.invoke(cli, ["--help"])
  46. assert (
  47. re.search(
  48. r"Commands:\n\s+"
  49. r"long\s+This is a long text that is too long to show as short help"
  50. r"\.\.\.\n\s+"
  51. r"short\s+This is a short text\.\n\s+"
  52. r"special-chars\s+Login and store the token in ~/.netrc\.\s*",
  53. result.output,
  54. )
  55. is not None
  56. )
  57. def test_no_args_is_help(runner):
  58. @click.command(no_args_is_help=True)
  59. def cli():
  60. pass
  61. result = runner.invoke(cli, [])
  62. assert result.exit_code == 0
  63. assert "Show this message and exit." in result.output
  64. def test_default_maps(runner):
  65. @click.group()
  66. def cli():
  67. pass
  68. @cli.command()
  69. @click.option("--name", default="normal")
  70. def foo(name):
  71. click.echo(name)
  72. result = runner.invoke(cli, ["foo"], default_map={"foo": {"name": "changed"}})
  73. assert not result.exception
  74. assert result.output == "changed\n"
  75. def test_group_with_args(runner):
  76. @click.group()
  77. @click.argument("obj")
  78. def cli(obj):
  79. click.echo("obj={}".format(obj))
  80. @cli.command()
  81. def move():
  82. click.echo("move")
  83. result = runner.invoke(cli, [])
  84. assert result.exit_code == 0
  85. assert "Show this message and exit." in result.output
  86. result = runner.invoke(cli, ["obj1"])
  87. assert result.exit_code == 2
  88. assert "Error: Missing command." in result.output
  89. result = runner.invoke(cli, ["obj1", "--help"])
  90. assert result.exit_code == 0
  91. assert "Show this message and exit." in result.output
  92. result = runner.invoke(cli, ["obj1", "move"])
  93. assert result.exit_code == 0
  94. assert result.output == "obj=obj1\nmove\n"
  95. def test_base_command(runner):
  96. import optparse
  97. @click.group()
  98. def cli():
  99. pass
  100. class OptParseCommand(click.BaseCommand):
  101. def __init__(self, name, parser, callback):
  102. click.BaseCommand.__init__(self, name)
  103. self.parser = parser
  104. self.callback = callback
  105. def parse_args(self, ctx, args):
  106. try:
  107. opts, args = parser.parse_args(args)
  108. except Exception as e:
  109. ctx.fail(str(e))
  110. ctx.args = args
  111. ctx.params = vars(opts)
  112. def get_usage(self, ctx):
  113. return self.parser.get_usage()
  114. def get_help(self, ctx):
  115. return self.parser.format_help()
  116. def invoke(self, ctx):
  117. ctx.invoke(self.callback, ctx.args, **ctx.params)
  118. parser = optparse.OptionParser(usage="Usage: foo test [OPTIONS]")
  119. parser.add_option(
  120. "-f", "--file", dest="filename", help="write report to FILE", metavar="FILE"
  121. )
  122. parser.add_option(
  123. "-q",
  124. "--quiet",
  125. action="store_false",
  126. dest="verbose",
  127. default=True,
  128. help="don't print status messages to stdout",
  129. )
  130. def test_callback(args, filename, verbose):
  131. click.echo(" ".join(args))
  132. click.echo(filename)
  133. click.echo(verbose)
  134. cli.add_command(OptParseCommand("test", parser, test_callback))
  135. result = runner.invoke(
  136. cli, ["test", "-f", "test.txt", "-q", "whatever.txt", "whateverelse.txt"]
  137. )
  138. assert not result.exception
  139. assert result.output.splitlines() == [
  140. "whatever.txt whateverelse.txt",
  141. "test.txt",
  142. "False",
  143. ]
  144. result = runner.invoke(cli, ["test", "--help"])
  145. assert not result.exception
  146. assert result.output.splitlines() == [
  147. "Usage: foo test [OPTIONS]",
  148. "",
  149. "Options:",
  150. " -h, --help show this help message and exit",
  151. " -f FILE, --file=FILE write report to FILE",
  152. " -q, --quiet don't print status messages to stdout",
  153. ]
  154. def test_object_propagation(runner):
  155. for chain in False, True:
  156. @click.group(chain=chain)
  157. @click.option("--debug/--no-debug", default=False)
  158. @click.pass_context
  159. def cli(ctx, debug):
  160. if ctx.obj is None:
  161. ctx.obj = {}
  162. ctx.obj["DEBUG"] = debug
  163. @cli.command()
  164. @click.pass_context
  165. def sync(ctx):
  166. click.echo("Debug is {}".format("on" if ctx.obj["DEBUG"] else "off"))
  167. result = runner.invoke(cli, ["sync"])
  168. assert result.exception is None
  169. assert result.output == "Debug is off\n"
  170. def test_other_command_invoke_with_defaults(runner):
  171. @click.command()
  172. @click.pass_context
  173. def cli(ctx):
  174. return ctx.invoke(other_cmd)
  175. @click.command()
  176. @click.option("--foo", type=click.INT, default=42)
  177. @click.pass_context
  178. def other_cmd(ctx, foo):
  179. assert ctx.info_name == "other-cmd"
  180. click.echo(foo)
  181. result = runner.invoke(cli, [])
  182. assert not result.exception
  183. assert result.output == "42\n"
  184. def test_invoked_subcommand(runner):
  185. @click.group(invoke_without_command=True)
  186. @click.pass_context
  187. def cli(ctx):
  188. if ctx.invoked_subcommand is None:
  189. click.echo("no subcommand, use default")
  190. ctx.invoke(sync)
  191. else:
  192. click.echo("invoke subcommand")
  193. @cli.command()
  194. def sync():
  195. click.echo("in subcommand")
  196. result = runner.invoke(cli, ["sync"])
  197. assert not result.exception
  198. assert result.output == "invoke subcommand\nin subcommand\n"
  199. result = runner.invoke(cli)
  200. assert not result.exception
  201. assert result.output == "no subcommand, use default\nin subcommand\n"
  202. def test_unprocessed_options(runner):
  203. @click.command(context_settings=dict(ignore_unknown_options=True))
  204. @click.argument("args", nargs=-1, type=click.UNPROCESSED)
  205. @click.option("--verbose", "-v", count=True)
  206. def cli(verbose, args):
  207. click.echo("Verbosity: {}".format(verbose))
  208. click.echo("Args: {}".format("|".join(args)))
  209. result = runner.invoke(cli, ["-foo", "-vvvvx", "--muhaha", "x", "y", "-x"])
  210. assert not result.exception
  211. assert result.output.splitlines() == [
  212. "Verbosity: 4",
  213. "Args: -foo|-x|--muhaha|x|y|-x",
  214. ]
  215. def test_deprecated_in_help_messages(runner):
  216. @click.command(deprecated=True)
  217. def cmd_with_help():
  218. """CLI HELP"""
  219. pass
  220. result = runner.invoke(cmd_with_help, ["--help"])
  221. assert "(DEPRECATED)" in result.output
  222. @click.command(deprecated=True)
  223. def cmd_without_help():
  224. pass
  225. result = runner.invoke(cmd_without_help, ["--help"])
  226. assert "(DEPRECATED)" in result.output
  227. def test_deprecated_in_invocation(runner):
  228. @click.command(deprecated=True)
  229. def deprecated_cmd():
  230. pass
  231. result = runner.invoke(deprecated_cmd)
  232. assert "DeprecationWarning:" in result.output